@optique/prompt 1.3.0-dev.2411 → 1.3.0-dev.2418
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/index.cjs +132 -8
- package/dist/index.d.cts +174 -3
- package/dist/index.d.ts +174 -3
- package/dist/index.js +130 -8
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -22,10 +22,117 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
24
|
const __optique_core_annotations = __toESM(require("@optique/core/annotations"));
|
|
25
|
+
const __optique_core_dependency = __toESM(require("@optique/core/dependency"));
|
|
26
|
+
const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
25
27
|
const __optique_core_extension = __toESM(require("@optique/core/extension"));
|
|
26
28
|
const __optique_core_fluent = __toESM(require("@optique/core/fluent"));
|
|
27
29
|
|
|
28
30
|
//#region src/index.ts
|
|
31
|
+
const derivedPromptConfigMarker = Symbol.for("@optique/prompt/derivedPromptConfig");
|
|
32
|
+
/**
|
|
33
|
+
* Checks whether a prompt configuration was created by
|
|
34
|
+
* {@link derivePromptConfig}.
|
|
35
|
+
*
|
|
36
|
+
* @param config The configuration to inspect.
|
|
37
|
+
* @returns `true` for a derived prompt configuration.
|
|
38
|
+
* @since 1.3.0
|
|
39
|
+
*/
|
|
40
|
+
function isDerivedPromptConfig(config) {
|
|
41
|
+
return config != null && typeof config === "object" && derivedPromptConfigMarker in config && config[derivedPromptConfigMarker] === true;
|
|
42
|
+
}
|
|
43
|
+
function derivePromptConfig(source, resolver, options) {
|
|
44
|
+
const isTuple = Array.isArray(source);
|
|
45
|
+
const dependencies = isTuple ? source : [source];
|
|
46
|
+
if (dependencies.length === 0) throw new TypeError("derivePromptConfig() requires at least one dependency source.");
|
|
47
|
+
const infos = dependencies.map(__optique_core_dependency.getDependencySourceInfo);
|
|
48
|
+
const singleDefault = options?.defaultValue;
|
|
49
|
+
const defaultValues = isTuple ? options?.defaultValues : singleDefault == null ? void 0 : () => [singleDefault()];
|
|
50
|
+
const resolve = isTuple ? (values, usedDefaults) => resolver(values, { usedDefaults }) : (values, usedDefaults) => resolver(values[0], { usedDefault: usedDefaults[0] });
|
|
51
|
+
return {
|
|
52
|
+
[derivedPromptConfigMarker]: true,
|
|
53
|
+
dependencies,
|
|
54
|
+
dependencyIds: infos.map((info) => info.sourceId),
|
|
55
|
+
dependencyLabels: infos.map((info, index) => info.metavar ?? `dependency #${index + 1}`),
|
|
56
|
+
resolve,
|
|
57
|
+
...defaultValues == null ? {} : { defaultValues },
|
|
58
|
+
...options?.when == null ? {} : {
|
|
59
|
+
when: options.when,
|
|
60
|
+
otherwise: options.otherwise
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function describeThrown(error) {
|
|
65
|
+
return error instanceof Error ? error.message : String(error);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolves a derived prompt configuration against the dependency runtime.
|
|
69
|
+
*
|
|
70
|
+
* A failed upstream source fails the resolution transitively—the resolver
|
|
71
|
+
* and the adapter never run. A missing source uses the configuration's
|
|
72
|
+
* declared default, or fails when none is declared. Resolver exceptions
|
|
73
|
+
* (synchronous throws and rejections alike) become prompt failures so
|
|
74
|
+
* the scheduler treats them like a cancelled prompt.
|
|
75
|
+
*/
|
|
76
|
+
async function resolveDerivedPromptConfig(config, exec, ownSourceId, ownLabel) {
|
|
77
|
+
const runtime = exec?.dependencyRuntime;
|
|
78
|
+
const ids = config.dependencyIds;
|
|
79
|
+
if (runtime != null) {
|
|
80
|
+
const failedIndex = ids.findIndex((id) => runtime.isSourceFailed(id));
|
|
81
|
+
if (failedIndex >= 0) {
|
|
82
|
+
runtime.propagateSourceFailure(ids, ownLabel ?? "prompt", ownSourceId);
|
|
83
|
+
const base = __optique_core_message.message`Cannot resolve prompt configuration: dependency ${config.dependencyLabels[failedIndex]} failed.`;
|
|
84
|
+
const chain = ownSourceId == null ? runtime.getSourceFailureChain(ids[failedIndex]) : void 0;
|
|
85
|
+
return {
|
|
86
|
+
ok: false,
|
|
87
|
+
error: chain == null || chain.length < 2 ? base : __optique_core_message.message`${base} Dependency chain: ${chain.join(" -> ")}.`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const missing = [];
|
|
92
|
+
const values = ids.map((id, index) => {
|
|
93
|
+
if (runtime?.hasSource(id) === true) return runtime.getSource(id);
|
|
94
|
+
missing.push(index);
|
|
95
|
+
return void 0;
|
|
96
|
+
});
|
|
97
|
+
const usedDefaults = ids.map(() => false);
|
|
98
|
+
if (missing.length > 0) {
|
|
99
|
+
if (config.defaultValues == null) {
|
|
100
|
+
const missingLabels = (0, __optique_core_message.values)(missing.map((index) => config.dependencyLabels[index]));
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
error: missing.length > 1 ? __optique_core_message.message`Cannot resolve prompt configuration: dependencies ${missingLabels} are not available and no default values are declared.` : __optique_core_message.message`Cannot resolve prompt configuration: dependency ${missingLabels} is not available and no default value is declared.`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
let defaults;
|
|
107
|
+
try {
|
|
108
|
+
defaults = config.defaultValues();
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
ok: false,
|
|
112
|
+
error: __optique_core_message.message`Prompt configuration default evaluation failed: ${describeThrown(error)}`
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (defaults.length !== ids.length) return {
|
|
116
|
+
ok: false,
|
|
117
|
+
error: __optique_core_message.message`Prompt configuration declared ${String(defaults.length)} default values for ${String(ids.length)} dependencies.`
|
|
118
|
+
};
|
|
119
|
+
for (const index of missing) {
|
|
120
|
+
values[index] = defaults[index];
|
|
121
|
+
usedDefaults[index] = true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
return {
|
|
126
|
+
ok: true,
|
|
127
|
+
config: await config.resolve(values, usedDefaults)
|
|
128
|
+
};
|
|
129
|
+
} catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
ok: false,
|
|
132
|
+
error: __optique_core_message.message`Prompt configuration resolution failed: ${describeThrown(error)}`
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
29
136
|
function shouldDeferPrompt(parser, state, exec) {
|
|
30
137
|
return typeof parser.shouldDeferCompletion === "function" && parser.shouldDeferCompletion(state, exec) === true;
|
|
31
138
|
}
|
|
@@ -60,6 +167,7 @@ function hasSourceBindingMarker(state) {
|
|
|
60
167
|
return state != null && typeof state === "object" && "hasCliValue" in state && Object.getOwnPropertySymbols(state).length > 0;
|
|
61
168
|
}
|
|
62
169
|
function readDefaultValue(adapter, config) {
|
|
170
|
+
if (isDerivedPromptConfig(config)) return void 0;
|
|
63
171
|
if (adapter.getDefaultValue != null) return adapter.getDefaultValue(config);
|
|
64
172
|
if (config != null && typeof config === "object" && "default" in config) return config.default;
|
|
65
173
|
return void 0;
|
|
@@ -82,7 +190,8 @@ function unwrapCompleteResult(result) {
|
|
|
82
190
|
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
83
191
|
* @param adapter Library-specific prompt executor.
|
|
84
192
|
* @returns A `prompt(parser, config)` wrapper that always produces an async
|
|
85
|
-
* parser.
|
|
193
|
+
* parser. The configuration may be a static `TConfig` or a
|
|
194
|
+
* {@link DerivedPromptConfig} whose resolver returns `TConfig`.
|
|
86
195
|
* @since 1.2.0
|
|
87
196
|
*/
|
|
88
197
|
function createPromptAdapter(adapter) {
|
|
@@ -131,12 +240,19 @@ function createPromptAdapter(adapter) {
|
|
|
131
240
|
if (cliStateIsInjectedAnnotationWrapper && requiresSourceBindingForAnnotationWrapper) return hasNestedSourceBinding;
|
|
132
241
|
return shouldAttemptInnerCompletion(cliState, state) || hasNestedSourceBinding;
|
|
133
242
|
}
|
|
134
|
-
async function executePrompt() {
|
|
243
|
+
async function executePrompt(exec) {
|
|
135
244
|
if (config.when != null && !await config.when()) return {
|
|
136
245
|
success: true,
|
|
137
246
|
value: config.otherwise
|
|
138
247
|
};
|
|
139
|
-
return adapter.execute(config);
|
|
248
|
+
if (!isDerivedPromptConfig(config)) return adapter.execute(config);
|
|
249
|
+
const source = promptedParser.dependencyMetadata?.source;
|
|
250
|
+
const resolved = await resolveDerivedPromptConfig(config, exec, source?.sourceId, source?.metavar);
|
|
251
|
+
if (!resolved.ok) return {
|
|
252
|
+
success: false,
|
|
253
|
+
error: resolved.error
|
|
254
|
+
};
|
|
255
|
+
return adapter.execute(resolved.config);
|
|
140
256
|
}
|
|
141
257
|
const parserInheritsAnnotations = (0, __optique_core_extension.getTraits)(parser).inheritsAnnotations === true;
|
|
142
258
|
const promptedParser = {
|
|
@@ -247,13 +363,15 @@ function createPromptAdapter(adapter) {
|
|
|
247
363
|
return Promise.resolve(cached);
|
|
248
364
|
}
|
|
249
365
|
if (session.policy === "demand-only" && !session.demanded.has(sourceId)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
250
|
-
|
|
366
|
+
if (session.policy === "demand-only" && isDerivedPromptConfig(config) && config.dependencyIds.some((id) => exec?.dependencyRuntime?.hasSource(id) !== true && exec?.dependencyRuntime?.isSourceFailed(id) !== true)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
367
|
+
return executePrompt(exec).then((result) => {
|
|
251
368
|
session.results.set(cacheKey, result);
|
|
252
369
|
session.effectfulSources.add(sourceId);
|
|
253
370
|
return result;
|
|
254
371
|
});
|
|
255
372
|
}
|
|
256
|
-
return
|
|
373
|
+
if (session?.policy === "demand-only" && isDerivedPromptConfig(config)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
374
|
+
return executePrompt(exec);
|
|
257
375
|
};
|
|
258
376
|
const hasDeferHook = typeof parser.shouldDeferCompletion === "function";
|
|
259
377
|
const decideFromParse = (parseResult) => {
|
|
@@ -337,8 +455,12 @@ function createPromptAdapter(adapter) {
|
|
|
337
455
|
},
|
|
338
456
|
completeSource: source.preservesSourceValue === false ? void 0 : (state, exec) => promptedParser.complete(state, exec)
|
|
339
457
|
}));
|
|
340
|
-
|
|
341
|
-
|
|
458
|
+
const composedMetadata = isDerivedPromptConfig(config) ? {
|
|
459
|
+
...dependencyMetadata ?? {},
|
|
460
|
+
completion: { dependencyIds: config.dependencyIds }
|
|
461
|
+
} : dependencyMetadata;
|
|
462
|
+
if (composedMetadata != null) Object.defineProperty(promptedParser, "dependencyMetadata", {
|
|
463
|
+
value: composedMetadata,
|
|
342
464
|
configurable: true,
|
|
343
465
|
enumerable: false
|
|
344
466
|
});
|
|
@@ -347,4 +469,6 @@ function createPromptAdapter(adapter) {
|
|
|
347
469
|
}
|
|
348
470
|
|
|
349
471
|
//#endregion
|
|
350
|
-
exports.createPromptAdapter = createPromptAdapter;
|
|
472
|
+
exports.createPromptAdapter = createPromptAdapter;
|
|
473
|
+
exports.derivePromptConfig = derivePromptConfig;
|
|
474
|
+
exports.isDerivedPromptConfig = isDerivedPromptConfig;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AnyDependencySource, DependencyValue, DependencyValues } from "@optique/core/dependency";
|
|
1
2
|
import { FluentParser } from "@optique/core/fluent";
|
|
2
3
|
import { Mode, Parser } from "@optique/core/parser";
|
|
3
4
|
import { ValueParserResult } from "@optique/core/valueparser";
|
|
@@ -57,6 +58,175 @@ interface PromptAdapter<TConfig> {
|
|
|
57
58
|
*/
|
|
58
59
|
readonly getDefaultValue?: (config: TConfig) => unknown;
|
|
59
60
|
}
|
|
61
|
+
declare const derivedPromptConfigMarker: unique symbol;
|
|
62
|
+
/**
|
|
63
|
+
* Context passed to a single-dependency prompt configuration resolver.
|
|
64
|
+
*
|
|
65
|
+
* @since 1.3.0
|
|
66
|
+
*/
|
|
67
|
+
interface DerivePromptConfigContext {
|
|
68
|
+
/**
|
|
69
|
+
* Whether the dependency value came from the `defaultValue` declared by
|
|
70
|
+
* this derived prompt configuration rather than a published source
|
|
71
|
+
* value. Source-level fallbacks such as `withDefault()` publish real
|
|
72
|
+
* values and are not reported here.
|
|
73
|
+
*/
|
|
74
|
+
readonly usedDefault: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Context passed to a multi-dependency prompt configuration resolver.
|
|
78
|
+
*
|
|
79
|
+
* @typeParam Deps Tuple of dependency sources the resolver reads.
|
|
80
|
+
* @since 1.3.0
|
|
81
|
+
*/
|
|
82
|
+
interface DerivePromptConfigsContext<Deps extends readonly AnyDependencySource[]> {
|
|
83
|
+
/**
|
|
84
|
+
* For each dependency position, whether the value came from the
|
|
85
|
+
* `defaultValues` declared by this derived prompt configuration rather
|
|
86
|
+
* than a published source value.
|
|
87
|
+
*/
|
|
88
|
+
readonly usedDefaults: { readonly [K in keyof Deps]: boolean };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Options for a single-dependency {@link derivePromptConfig} call.
|
|
92
|
+
*
|
|
93
|
+
* @typeParam TDefault Value type of the dependency source.
|
|
94
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
95
|
+
* @since 1.3.0
|
|
96
|
+
*/
|
|
97
|
+
type DerivePromptConfigOptions<TDefault, TOtherwise> = {
|
|
98
|
+
/**
|
|
99
|
+
* Lazily evaluated fallback used when the dependency source has not
|
|
100
|
+
* published a value. Without it, an unresolved dependency fails the
|
|
101
|
+
* prompt instead of running the resolver.
|
|
102
|
+
*/
|
|
103
|
+
readonly defaultValue?: () => TDefault;
|
|
104
|
+
} & ({
|
|
105
|
+
readonly when?: never;
|
|
106
|
+
readonly otherwise?: never;
|
|
107
|
+
} | {
|
|
108
|
+
readonly when: () => boolean | Promise<boolean>;
|
|
109
|
+
readonly otherwise: TOtherwise;
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* Options for a multi-dependency {@link derivePromptConfig} call.
|
|
113
|
+
*
|
|
114
|
+
* @typeParam TDefaults Tuple of dependency source value types.
|
|
115
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
116
|
+
* @since 1.3.0
|
|
117
|
+
*/
|
|
118
|
+
type DerivePromptConfigsOptions<TDefaults extends readonly unknown[], TOtherwise> = {
|
|
119
|
+
/**
|
|
120
|
+
* Lazily evaluated fallbacks used for dependency sources that have
|
|
121
|
+
* not published a value. The thunk must return one value per
|
|
122
|
+
* dependency. Without it, an unresolved dependency fails the prompt
|
|
123
|
+
* instead of running the resolver.
|
|
124
|
+
*/
|
|
125
|
+
readonly defaultValues?: () => TDefaults;
|
|
126
|
+
} & ({
|
|
127
|
+
readonly when?: never;
|
|
128
|
+
readonly otherwise?: never;
|
|
129
|
+
} | {
|
|
130
|
+
readonly when: () => boolean | Promise<boolean>;
|
|
131
|
+
readonly otherwise: TOtherwise;
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* A prompt configuration derived from dependency source values, created
|
|
135
|
+
* by {@link derivePromptConfig}.
|
|
136
|
+
*
|
|
137
|
+
* The resolver runs during the real completion phase, immediately before
|
|
138
|
+
* the adapter executes, and never during probes, help, or suggestions.
|
|
139
|
+
* Generated documentation therefore cannot reflect a derived
|
|
140
|
+
* configuration and falls back to the wrapped parser's static metadata.
|
|
141
|
+
*
|
|
142
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
143
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
144
|
+
* @since 1.3.0
|
|
145
|
+
*/
|
|
146
|
+
interface DerivedPromptConfig<TConfig, TOtherwise = never> {
|
|
147
|
+
readonly [derivedPromptConfigMarker]: true;
|
|
148
|
+
/** The dependency sources the resolver reads, in declaration order. */
|
|
149
|
+
readonly dependencies: readonly AnyDependencySource[];
|
|
150
|
+
/** Snapshot of the dependency source identities. @internal */
|
|
151
|
+
readonly dependencyIds: readonly symbol[];
|
|
152
|
+
/** Diagnostic labels matching {@link dependencyIds}. @internal */
|
|
153
|
+
readonly dependencyLabels: readonly string[];
|
|
154
|
+
/**
|
|
155
|
+
* Resolves the adapter configuration from dependency values. Receives
|
|
156
|
+
* one value and one used-default flag per dependency position.
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
readonly resolve: (values: readonly unknown[], usedDefaults: readonly boolean[]) => TConfig | Promise<TConfig>;
|
|
160
|
+
/**
|
|
161
|
+
* Lazily evaluated fallbacks, one per dependency position.
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
readonly defaultValues?: () => readonly unknown[];
|
|
165
|
+
/** Runtime condition, evaluated before the resolver. */
|
|
166
|
+
readonly when?: () => boolean | Promise<boolean>;
|
|
167
|
+
/** Value produced when {@link when} returns `false`. */
|
|
168
|
+
readonly otherwise?: TOtherwise;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Checks whether a prompt configuration was created by
|
|
172
|
+
* {@link derivePromptConfig}.
|
|
173
|
+
*
|
|
174
|
+
* @param config The configuration to inspect.
|
|
175
|
+
* @returns `true` for a derived prompt configuration.
|
|
176
|
+
* @since 1.3.0
|
|
177
|
+
*/
|
|
178
|
+
declare function isDerivedPromptConfig(config: unknown): config is DerivedPromptConfig<unknown, unknown>;
|
|
179
|
+
/**
|
|
180
|
+
* Derives a prompt configuration from one dependency source value.
|
|
181
|
+
*
|
|
182
|
+
* The resolver may return the configuration synchronously or
|
|
183
|
+
* asynchronously. It runs only during the real completion phase, after
|
|
184
|
+
* the named source has published its value—whether that value came from
|
|
185
|
+
* the command line, a source binding, or another prompt.
|
|
186
|
+
*
|
|
187
|
+
* @typeParam D The dependency source type.
|
|
188
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
189
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
190
|
+
* @param source The dependency source the resolver reads.
|
|
191
|
+
* @param resolver Produces the adapter configuration from the source
|
|
192
|
+
* value.
|
|
193
|
+
* @param options Optional declared default and runtime condition.
|
|
194
|
+
* @returns A derived configuration accepted by `prompt()` wrappers.
|
|
195
|
+
* @throws {TypeError} If `source` is not a dependency source.
|
|
196
|
+
* @since 1.3.0
|
|
197
|
+
*/
|
|
198
|
+
declare function derivePromptConfig<D extends AnyDependencySource, TConfig, const TOtherwise = never>(source: D, resolver: (value: DependencyValue<D>, context: DerivePromptConfigContext) => TConfig | Promise<TConfig>, options?: DerivePromptConfigOptions<DependencyValue<D>, TOtherwise>): DerivedPromptConfig<TConfig, TOtherwise>;
|
|
199
|
+
/**
|
|
200
|
+
* Derives a prompt configuration from multiple dependency source values.
|
|
201
|
+
*
|
|
202
|
+
* The resolver receives the values as a tuple matching the declaration
|
|
203
|
+
* order of `sources`. Evaluation order among prompts follows the
|
|
204
|
+
* dependency graph, not surrounding object or tuple field order.
|
|
205
|
+
*
|
|
206
|
+
* @typeParam Deps Tuple of dependency sources the resolver reads.
|
|
207
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
208
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
209
|
+
* @param sources The dependency sources, at least one.
|
|
210
|
+
* @param resolver Produces the adapter configuration from the source
|
|
211
|
+
* values.
|
|
212
|
+
* @param options Optional declared defaults and runtime condition.
|
|
213
|
+
* @returns A derived configuration accepted by `prompt()` wrappers.
|
|
214
|
+
* @throws {TypeError} If `sources` is empty or contains a value that is
|
|
215
|
+
* not a dependency source.
|
|
216
|
+
* @since 1.3.0
|
|
217
|
+
*/
|
|
218
|
+
declare function derivePromptConfig<const Deps extends readonly [AnyDependencySource, ...AnyDependencySource[]], TConfig, const TOtherwise = never>(sources: Deps, resolver: (values: DependencyValues<Deps>, context: DerivePromptConfigsContext<Deps>) => TConfig | Promise<TConfig>, options?: DerivePromptConfigsOptions<DependencyValues<Deps>, TOtherwise>): DerivedPromptConfig<TConfig, TOtherwise>;
|
|
219
|
+
/**
|
|
220
|
+
* Prompt configuration accepted by a generated `prompt()` wrapper: either
|
|
221
|
+
* a static adapter configuration (optionally with a runtime condition) or
|
|
222
|
+
* a configuration derived from dependency sources via
|
|
223
|
+
* {@link derivePromptConfig}.
|
|
224
|
+
*
|
|
225
|
+
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
226
|
+
* @typeParam TValue Value type produced by the wrapped parser.
|
|
227
|
+
* @since 1.3.0
|
|
228
|
+
*/
|
|
229
|
+
type PromptConfigInput<TConfig, TValue> = (TConfig & PromptCondition<TValue>) | DerivedPromptConfig<TConfig, NoInfer<TValue>>;
|
|
60
230
|
/**
|
|
61
231
|
* Creates a `prompt()` parser wrapper for a prompt library adapter.
|
|
62
232
|
*
|
|
@@ -68,9 +238,10 @@ interface PromptAdapter<TConfig> {
|
|
|
68
238
|
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
69
239
|
* @param adapter Library-specific prompt executor.
|
|
70
240
|
* @returns A `prompt(parser, config)` wrapper that always produces an async
|
|
71
|
-
* parser.
|
|
241
|
+
* parser. The configuration may be a static `TConfig` or a
|
|
242
|
+
* {@link DerivedPromptConfig} whose resolver returns `TConfig`.
|
|
72
243
|
* @since 1.2.0
|
|
73
244
|
*/
|
|
74
|
-
declare function createPromptAdapter<TConfig>(adapter: PromptAdapter<TConfig>): <M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: TConfig
|
|
245
|
+
declare function createPromptAdapter<TConfig>(adapter: PromptAdapter<TConfig>): <M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfigInput<TConfig, TValue>) => FluentParser<"async", TValue, TState>;
|
|
75
246
|
//#endregion
|
|
76
|
-
export { PromptAdapter, PromptCondition, createPromptAdapter };
|
|
247
|
+
export { DerivePromptConfigContext, DerivePromptConfigOptions, DerivePromptConfigsContext, DerivePromptConfigsOptions, DerivedPromptConfig, PromptAdapter, PromptCondition, PromptConfigInput, createPromptAdapter, derivePromptConfig, isDerivedPromptConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AnyDependencySource, DependencyValue, DependencyValues } from "@optique/core/dependency";
|
|
1
2
|
import { FluentParser } from "@optique/core/fluent";
|
|
2
3
|
import { Mode, Parser } from "@optique/core/parser";
|
|
3
4
|
import { ValueParserResult } from "@optique/core/valueparser";
|
|
@@ -57,6 +58,175 @@ interface PromptAdapter<TConfig> {
|
|
|
57
58
|
*/
|
|
58
59
|
readonly getDefaultValue?: (config: TConfig) => unknown;
|
|
59
60
|
}
|
|
61
|
+
declare const derivedPromptConfigMarker: unique symbol;
|
|
62
|
+
/**
|
|
63
|
+
* Context passed to a single-dependency prompt configuration resolver.
|
|
64
|
+
*
|
|
65
|
+
* @since 1.3.0
|
|
66
|
+
*/
|
|
67
|
+
interface DerivePromptConfigContext {
|
|
68
|
+
/**
|
|
69
|
+
* Whether the dependency value came from the `defaultValue` declared by
|
|
70
|
+
* this derived prompt configuration rather than a published source
|
|
71
|
+
* value. Source-level fallbacks such as `withDefault()` publish real
|
|
72
|
+
* values and are not reported here.
|
|
73
|
+
*/
|
|
74
|
+
readonly usedDefault: boolean;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Context passed to a multi-dependency prompt configuration resolver.
|
|
78
|
+
*
|
|
79
|
+
* @typeParam Deps Tuple of dependency sources the resolver reads.
|
|
80
|
+
* @since 1.3.0
|
|
81
|
+
*/
|
|
82
|
+
interface DerivePromptConfigsContext<Deps extends readonly AnyDependencySource[]> {
|
|
83
|
+
/**
|
|
84
|
+
* For each dependency position, whether the value came from the
|
|
85
|
+
* `defaultValues` declared by this derived prompt configuration rather
|
|
86
|
+
* than a published source value.
|
|
87
|
+
*/
|
|
88
|
+
readonly usedDefaults: { readonly [K in keyof Deps]: boolean };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Options for a single-dependency {@link derivePromptConfig} call.
|
|
92
|
+
*
|
|
93
|
+
* @typeParam TDefault Value type of the dependency source.
|
|
94
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
95
|
+
* @since 1.3.0
|
|
96
|
+
*/
|
|
97
|
+
type DerivePromptConfigOptions<TDefault, TOtherwise> = {
|
|
98
|
+
/**
|
|
99
|
+
* Lazily evaluated fallback used when the dependency source has not
|
|
100
|
+
* published a value. Without it, an unresolved dependency fails the
|
|
101
|
+
* prompt instead of running the resolver.
|
|
102
|
+
*/
|
|
103
|
+
readonly defaultValue?: () => TDefault;
|
|
104
|
+
} & ({
|
|
105
|
+
readonly when?: never;
|
|
106
|
+
readonly otherwise?: never;
|
|
107
|
+
} | {
|
|
108
|
+
readonly when: () => boolean | Promise<boolean>;
|
|
109
|
+
readonly otherwise: TOtherwise;
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* Options for a multi-dependency {@link derivePromptConfig} call.
|
|
113
|
+
*
|
|
114
|
+
* @typeParam TDefaults Tuple of dependency source value types.
|
|
115
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
116
|
+
* @since 1.3.0
|
|
117
|
+
*/
|
|
118
|
+
type DerivePromptConfigsOptions<TDefaults extends readonly unknown[], TOtherwise> = {
|
|
119
|
+
/**
|
|
120
|
+
* Lazily evaluated fallbacks used for dependency sources that have
|
|
121
|
+
* not published a value. The thunk must return one value per
|
|
122
|
+
* dependency. Without it, an unresolved dependency fails the prompt
|
|
123
|
+
* instead of running the resolver.
|
|
124
|
+
*/
|
|
125
|
+
readonly defaultValues?: () => TDefaults;
|
|
126
|
+
} & ({
|
|
127
|
+
readonly when?: never;
|
|
128
|
+
readonly otherwise?: never;
|
|
129
|
+
} | {
|
|
130
|
+
readonly when: () => boolean | Promise<boolean>;
|
|
131
|
+
readonly otherwise: TOtherwise;
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* A prompt configuration derived from dependency source values, created
|
|
135
|
+
* by {@link derivePromptConfig}.
|
|
136
|
+
*
|
|
137
|
+
* The resolver runs during the real completion phase, immediately before
|
|
138
|
+
* the adapter executes, and never during probes, help, or suggestions.
|
|
139
|
+
* Generated documentation therefore cannot reflect a derived
|
|
140
|
+
* configuration and falls back to the wrapped parser's static metadata.
|
|
141
|
+
*
|
|
142
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
143
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
144
|
+
* @since 1.3.0
|
|
145
|
+
*/
|
|
146
|
+
interface DerivedPromptConfig<TConfig, TOtherwise = never> {
|
|
147
|
+
readonly [derivedPromptConfigMarker]: true;
|
|
148
|
+
/** The dependency sources the resolver reads, in declaration order. */
|
|
149
|
+
readonly dependencies: readonly AnyDependencySource[];
|
|
150
|
+
/** Snapshot of the dependency source identities. @internal */
|
|
151
|
+
readonly dependencyIds: readonly symbol[];
|
|
152
|
+
/** Diagnostic labels matching {@link dependencyIds}. @internal */
|
|
153
|
+
readonly dependencyLabels: readonly string[];
|
|
154
|
+
/**
|
|
155
|
+
* Resolves the adapter configuration from dependency values. Receives
|
|
156
|
+
* one value and one used-default flag per dependency position.
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
readonly resolve: (values: readonly unknown[], usedDefaults: readonly boolean[]) => TConfig | Promise<TConfig>;
|
|
160
|
+
/**
|
|
161
|
+
* Lazily evaluated fallbacks, one per dependency position.
|
|
162
|
+
* @internal
|
|
163
|
+
*/
|
|
164
|
+
readonly defaultValues?: () => readonly unknown[];
|
|
165
|
+
/** Runtime condition, evaluated before the resolver. */
|
|
166
|
+
readonly when?: () => boolean | Promise<boolean>;
|
|
167
|
+
/** Value produced when {@link when} returns `false`. */
|
|
168
|
+
readonly otherwise?: TOtherwise;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Checks whether a prompt configuration was created by
|
|
172
|
+
* {@link derivePromptConfig}.
|
|
173
|
+
*
|
|
174
|
+
* @param config The configuration to inspect.
|
|
175
|
+
* @returns `true` for a derived prompt configuration.
|
|
176
|
+
* @since 1.3.0
|
|
177
|
+
*/
|
|
178
|
+
declare function isDerivedPromptConfig(config: unknown): config is DerivedPromptConfig<unknown, unknown>;
|
|
179
|
+
/**
|
|
180
|
+
* Derives a prompt configuration from one dependency source value.
|
|
181
|
+
*
|
|
182
|
+
* The resolver may return the configuration synchronously or
|
|
183
|
+
* asynchronously. It runs only during the real completion phase, after
|
|
184
|
+
* the named source has published its value—whether that value came from
|
|
185
|
+
* the command line, a source binding, or another prompt.
|
|
186
|
+
*
|
|
187
|
+
* @typeParam D The dependency source type.
|
|
188
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
189
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
190
|
+
* @param source The dependency source the resolver reads.
|
|
191
|
+
* @param resolver Produces the adapter configuration from the source
|
|
192
|
+
* value.
|
|
193
|
+
* @param options Optional declared default and runtime condition.
|
|
194
|
+
* @returns A derived configuration accepted by `prompt()` wrappers.
|
|
195
|
+
* @throws {TypeError} If `source` is not a dependency source.
|
|
196
|
+
* @since 1.3.0
|
|
197
|
+
*/
|
|
198
|
+
declare function derivePromptConfig<D extends AnyDependencySource, TConfig, const TOtherwise = never>(source: D, resolver: (value: DependencyValue<D>, context: DerivePromptConfigContext) => TConfig | Promise<TConfig>, options?: DerivePromptConfigOptions<DependencyValue<D>, TOtherwise>): DerivedPromptConfig<TConfig, TOtherwise>;
|
|
199
|
+
/**
|
|
200
|
+
* Derives a prompt configuration from multiple dependency source values.
|
|
201
|
+
*
|
|
202
|
+
* The resolver receives the values as a tuple matching the declaration
|
|
203
|
+
* order of `sources`. Evaluation order among prompts follows the
|
|
204
|
+
* dependency graph, not surrounding object or tuple field order.
|
|
205
|
+
*
|
|
206
|
+
* @typeParam Deps Tuple of dependency sources the resolver reads.
|
|
207
|
+
* @typeParam TConfig Adapter configuration produced by the resolver.
|
|
208
|
+
* @typeParam TOtherwise Value type returned when `when` skips the prompt.
|
|
209
|
+
* @param sources The dependency sources, at least one.
|
|
210
|
+
* @param resolver Produces the adapter configuration from the source
|
|
211
|
+
* values.
|
|
212
|
+
* @param options Optional declared defaults and runtime condition.
|
|
213
|
+
* @returns A derived configuration accepted by `prompt()` wrappers.
|
|
214
|
+
* @throws {TypeError} If `sources` is empty or contains a value that is
|
|
215
|
+
* not a dependency source.
|
|
216
|
+
* @since 1.3.0
|
|
217
|
+
*/
|
|
218
|
+
declare function derivePromptConfig<const Deps extends readonly [AnyDependencySource, ...AnyDependencySource[]], TConfig, const TOtherwise = never>(sources: Deps, resolver: (values: DependencyValues<Deps>, context: DerivePromptConfigsContext<Deps>) => TConfig | Promise<TConfig>, options?: DerivePromptConfigsOptions<DependencyValues<Deps>, TOtherwise>): DerivedPromptConfig<TConfig, TOtherwise>;
|
|
219
|
+
/**
|
|
220
|
+
* Prompt configuration accepted by a generated `prompt()` wrapper: either
|
|
221
|
+
* a static adapter configuration (optionally with a runtime condition) or
|
|
222
|
+
* a configuration derived from dependency sources via
|
|
223
|
+
* {@link derivePromptConfig}.
|
|
224
|
+
*
|
|
225
|
+
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
226
|
+
* @typeParam TValue Value type produced by the wrapped parser.
|
|
227
|
+
* @since 1.3.0
|
|
228
|
+
*/
|
|
229
|
+
type PromptConfigInput<TConfig, TValue> = (TConfig & PromptCondition<TValue>) | DerivedPromptConfig<TConfig, NoInfer<TValue>>;
|
|
60
230
|
/**
|
|
61
231
|
* Creates a `prompt()` parser wrapper for a prompt library adapter.
|
|
62
232
|
*
|
|
@@ -68,9 +238,10 @@ interface PromptAdapter<TConfig> {
|
|
|
68
238
|
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
69
239
|
* @param adapter Library-specific prompt executor.
|
|
70
240
|
* @returns A `prompt(parser, config)` wrapper that always produces an async
|
|
71
|
-
* parser.
|
|
241
|
+
* parser. The configuration may be a static `TConfig` or a
|
|
242
|
+
* {@link DerivedPromptConfig} whose resolver returns `TConfig`.
|
|
72
243
|
* @since 1.2.0
|
|
73
244
|
*/
|
|
74
|
-
declare function createPromptAdapter<TConfig>(adapter: PromptAdapter<TConfig>): <M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: TConfig
|
|
245
|
+
declare function createPromptAdapter<TConfig>(adapter: PromptAdapter<TConfig>): <M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfigInput<TConfig, TValue>) => FluentParser<"async", TValue, TState>;
|
|
75
246
|
//#endregion
|
|
76
|
-
export { PromptAdapter, PromptCondition, createPromptAdapter };
|
|
247
|
+
export { DerivePromptConfigContext, DerivePromptConfigOptions, DerivePromptConfigsContext, DerivePromptConfigsOptions, DerivedPromptConfig, PromptAdapter, PromptCondition, PromptConfigInput, createPromptAdapter, derivePromptConfig, isDerivedPromptConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,115 @@
|
|
|
1
1
|
import { getAnnotations } from "@optique/core/annotations";
|
|
2
|
+
import { getDependencySourceInfo } from "@optique/core/dependency";
|
|
3
|
+
import { message, values } from "@optique/core/message";
|
|
2
4
|
import { defineTraits, delegateSuggestNodes, getTraits, inheritAnnotations, injectAnnotations, mapSourceMetadata, unwrapInjectedAnnotationState, withAnnotationView } from "@optique/core/extension";
|
|
3
5
|
import { fluent } from "@optique/core/fluent";
|
|
4
6
|
|
|
5
7
|
//#region src/index.ts
|
|
8
|
+
const derivedPromptConfigMarker = Symbol.for("@optique/prompt/derivedPromptConfig");
|
|
9
|
+
/**
|
|
10
|
+
* Checks whether a prompt configuration was created by
|
|
11
|
+
* {@link derivePromptConfig}.
|
|
12
|
+
*
|
|
13
|
+
* @param config The configuration to inspect.
|
|
14
|
+
* @returns `true` for a derived prompt configuration.
|
|
15
|
+
* @since 1.3.0
|
|
16
|
+
*/
|
|
17
|
+
function isDerivedPromptConfig(config) {
|
|
18
|
+
return config != null && typeof config === "object" && derivedPromptConfigMarker in config && config[derivedPromptConfigMarker] === true;
|
|
19
|
+
}
|
|
20
|
+
function derivePromptConfig(source, resolver, options) {
|
|
21
|
+
const isTuple = Array.isArray(source);
|
|
22
|
+
const dependencies = isTuple ? source : [source];
|
|
23
|
+
if (dependencies.length === 0) throw new TypeError("derivePromptConfig() requires at least one dependency source.");
|
|
24
|
+
const infos = dependencies.map(getDependencySourceInfo);
|
|
25
|
+
const singleDefault = options?.defaultValue;
|
|
26
|
+
const defaultValues = isTuple ? options?.defaultValues : singleDefault == null ? void 0 : () => [singleDefault()];
|
|
27
|
+
const resolve = isTuple ? (values$1, usedDefaults) => resolver(values$1, { usedDefaults }) : (values$1, usedDefaults) => resolver(values$1[0], { usedDefault: usedDefaults[0] });
|
|
28
|
+
return {
|
|
29
|
+
[derivedPromptConfigMarker]: true,
|
|
30
|
+
dependencies,
|
|
31
|
+
dependencyIds: infos.map((info) => info.sourceId),
|
|
32
|
+
dependencyLabels: infos.map((info, index) => info.metavar ?? `dependency #${index + 1}`),
|
|
33
|
+
resolve,
|
|
34
|
+
...defaultValues == null ? {} : { defaultValues },
|
|
35
|
+
...options?.when == null ? {} : {
|
|
36
|
+
when: options.when,
|
|
37
|
+
otherwise: options.otherwise
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function describeThrown(error) {
|
|
42
|
+
return error instanceof Error ? error.message : String(error);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a derived prompt configuration against the dependency runtime.
|
|
46
|
+
*
|
|
47
|
+
* A failed upstream source fails the resolution transitively—the resolver
|
|
48
|
+
* and the adapter never run. A missing source uses the configuration's
|
|
49
|
+
* declared default, or fails when none is declared. Resolver exceptions
|
|
50
|
+
* (synchronous throws and rejections alike) become prompt failures so
|
|
51
|
+
* the scheduler treats them like a cancelled prompt.
|
|
52
|
+
*/
|
|
53
|
+
async function resolveDerivedPromptConfig(config, exec, ownSourceId, ownLabel) {
|
|
54
|
+
const runtime = exec?.dependencyRuntime;
|
|
55
|
+
const ids = config.dependencyIds;
|
|
56
|
+
if (runtime != null) {
|
|
57
|
+
const failedIndex = ids.findIndex((id) => runtime.isSourceFailed(id));
|
|
58
|
+
if (failedIndex >= 0) {
|
|
59
|
+
runtime.propagateSourceFailure(ids, ownLabel ?? "prompt", ownSourceId);
|
|
60
|
+
const base = message`Cannot resolve prompt configuration: dependency ${config.dependencyLabels[failedIndex]} failed.`;
|
|
61
|
+
const chain = ownSourceId == null ? runtime.getSourceFailureChain(ids[failedIndex]) : void 0;
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
error: chain == null || chain.length < 2 ? base : message`${base} Dependency chain: ${chain.join(" -> ")}.`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const missing = [];
|
|
69
|
+
const values$1 = ids.map((id, index) => {
|
|
70
|
+
if (runtime?.hasSource(id) === true) return runtime.getSource(id);
|
|
71
|
+
missing.push(index);
|
|
72
|
+
return void 0;
|
|
73
|
+
});
|
|
74
|
+
const usedDefaults = ids.map(() => false);
|
|
75
|
+
if (missing.length > 0) {
|
|
76
|
+
if (config.defaultValues == null) {
|
|
77
|
+
const missingLabels = values(missing.map((index) => config.dependencyLabels[index]));
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
error: missing.length > 1 ? message`Cannot resolve prompt configuration: dependencies ${missingLabels} are not available and no default values are declared.` : message`Cannot resolve prompt configuration: dependency ${missingLabels} is not available and no default value is declared.`
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let defaults;
|
|
84
|
+
try {
|
|
85
|
+
defaults = config.defaultValues();
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
error: message`Prompt configuration default evaluation failed: ${describeThrown(error)}`
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (defaults.length !== ids.length) return {
|
|
93
|
+
ok: false,
|
|
94
|
+
error: message`Prompt configuration declared ${String(defaults.length)} default values for ${String(ids.length)} dependencies.`
|
|
95
|
+
};
|
|
96
|
+
for (const index of missing) {
|
|
97
|
+
values$1[index] = defaults[index];
|
|
98
|
+
usedDefaults[index] = true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
return {
|
|
103
|
+
ok: true,
|
|
104
|
+
config: await config.resolve(values$1, usedDefaults)
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
error: message`Prompt configuration resolution failed: ${describeThrown(error)}`
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
6
113
|
function shouldDeferPrompt(parser, state, exec) {
|
|
7
114
|
return typeof parser.shouldDeferCompletion === "function" && parser.shouldDeferCompletion(state, exec) === true;
|
|
8
115
|
}
|
|
@@ -37,6 +144,7 @@ function hasSourceBindingMarker(state) {
|
|
|
37
144
|
return state != null && typeof state === "object" && "hasCliValue" in state && Object.getOwnPropertySymbols(state).length > 0;
|
|
38
145
|
}
|
|
39
146
|
function readDefaultValue(adapter, config) {
|
|
147
|
+
if (isDerivedPromptConfig(config)) return void 0;
|
|
40
148
|
if (adapter.getDefaultValue != null) return adapter.getDefaultValue(config);
|
|
41
149
|
if (config != null && typeof config === "object" && "default" in config) return config.default;
|
|
42
150
|
return void 0;
|
|
@@ -59,7 +167,8 @@ function unwrapCompleteResult(result) {
|
|
|
59
167
|
* @typeParam TConfig Prompt configuration accepted by the adapter.
|
|
60
168
|
* @param adapter Library-specific prompt executor.
|
|
61
169
|
* @returns A `prompt(parser, config)` wrapper that always produces an async
|
|
62
|
-
* parser.
|
|
170
|
+
* parser. The configuration may be a static `TConfig` or a
|
|
171
|
+
* {@link DerivedPromptConfig} whose resolver returns `TConfig`.
|
|
63
172
|
* @since 1.2.0
|
|
64
173
|
*/
|
|
65
174
|
function createPromptAdapter(adapter) {
|
|
@@ -108,12 +217,19 @@ function createPromptAdapter(adapter) {
|
|
|
108
217
|
if (cliStateIsInjectedAnnotationWrapper && requiresSourceBindingForAnnotationWrapper) return hasNestedSourceBinding;
|
|
109
218
|
return shouldAttemptInnerCompletion(cliState, state) || hasNestedSourceBinding;
|
|
110
219
|
}
|
|
111
|
-
async function executePrompt() {
|
|
220
|
+
async function executePrompt(exec) {
|
|
112
221
|
if (config.when != null && !await config.when()) return {
|
|
113
222
|
success: true,
|
|
114
223
|
value: config.otherwise
|
|
115
224
|
};
|
|
116
|
-
return adapter.execute(config);
|
|
225
|
+
if (!isDerivedPromptConfig(config)) return adapter.execute(config);
|
|
226
|
+
const source = promptedParser.dependencyMetadata?.source;
|
|
227
|
+
const resolved = await resolveDerivedPromptConfig(config, exec, source?.sourceId, source?.metavar);
|
|
228
|
+
if (!resolved.ok) return {
|
|
229
|
+
success: false,
|
|
230
|
+
error: resolved.error
|
|
231
|
+
};
|
|
232
|
+
return adapter.execute(resolved.config);
|
|
117
233
|
}
|
|
118
234
|
const parserInheritsAnnotations = getTraits(parser).inheritsAnnotations === true;
|
|
119
235
|
const promptedParser = {
|
|
@@ -224,13 +340,15 @@ function createPromptAdapter(adapter) {
|
|
|
224
340
|
return Promise.resolve(cached);
|
|
225
341
|
}
|
|
226
342
|
if (session.policy === "demand-only" && !session.demanded.has(sourceId)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
227
|
-
|
|
343
|
+
if (session.policy === "demand-only" && isDerivedPromptConfig(config) && config.dependencyIds.some((id) => exec?.dependencyRuntime?.hasSource(id) !== true && exec?.dependencyRuntime?.isSourceFailed(id) !== true)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
344
|
+
return executePrompt(exec).then((result) => {
|
|
228
345
|
session.results.set(cacheKey, result);
|
|
229
346
|
session.effectfulSources.add(sourceId);
|
|
230
347
|
return result;
|
|
231
348
|
});
|
|
232
349
|
}
|
|
233
|
-
return
|
|
350
|
+
if (session?.policy === "demand-only" && isDerivedPromptConfig(config)) return Promise.resolve(deferredPromptResult(readPlaceholder()));
|
|
351
|
+
return executePrompt(exec);
|
|
234
352
|
};
|
|
235
353
|
const hasDeferHook = typeof parser.shouldDeferCompletion === "function";
|
|
236
354
|
const decideFromParse = (parseResult) => {
|
|
@@ -314,8 +432,12 @@ function createPromptAdapter(adapter) {
|
|
|
314
432
|
},
|
|
315
433
|
completeSource: source.preservesSourceValue === false ? void 0 : (state, exec) => promptedParser.complete(state, exec)
|
|
316
434
|
}));
|
|
317
|
-
|
|
318
|
-
|
|
435
|
+
const composedMetadata = isDerivedPromptConfig(config) ? {
|
|
436
|
+
...dependencyMetadata ?? {},
|
|
437
|
+
completion: { dependencyIds: config.dependencyIds }
|
|
438
|
+
} : dependencyMetadata;
|
|
439
|
+
if (composedMetadata != null) Object.defineProperty(promptedParser, "dependencyMetadata", {
|
|
440
|
+
value: composedMetadata,
|
|
319
441
|
configurable: true,
|
|
320
442
|
enumerable: false
|
|
321
443
|
});
|
|
@@ -324,4 +446,4 @@ function createPromptAdapter(adapter) {
|
|
|
324
446
|
}
|
|
325
447
|
|
|
326
448
|
//#endregion
|
|
327
|
-
export { createPromptAdapter };
|
|
449
|
+
export { createPromptAdapter, derivePromptConfig, isDerivedPromptConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/prompt",
|
|
3
|
-
"version": "1.3.0-dev.
|
|
3
|
+
"version": "1.3.0-dev.2418",
|
|
4
4
|
"description": "Generic prompt adapter support for Optique",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -60,12 +60,12 @@
|
|
|
60
60
|
},
|
|
61
61
|
"sideEffects": false,
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@optique/core": "1.3.0-dev.
|
|
63
|
+
"@optique/core": "1.3.0-dev.2418+afa5cda1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@optique/config": "1.3.0-dev.
|
|
67
|
-
"@optique/env": "1.3.0-dev.
|
|
68
|
-
"@optique/run": "1.3.0-dev.
|
|
66
|
+
"@optique/config": "1.3.0-dev.2418+afa5cda1",
|
|
67
|
+
"@optique/env": "1.3.0-dev.2418+afa5cda1",
|
|
68
|
+
"@optique/run": "1.3.0-dev.2418+afa5cda1",
|
|
69
69
|
"@types/node": "^24.0.0",
|
|
70
70
|
"fast-check": "^4.7.0",
|
|
71
71
|
"tsdown": "^0.13.0",
|