@fgv/ts-extras 5.1.0-21 → 5.1.0-23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/packlets/ai-assist/index.js +2 -0
  2. package/dist/packlets/ai-assist/index.js.map +1 -1
  3. package/dist/packlets/ai-assist/jsonCompletion.js +95 -0
  4. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  5. package/dist/packlets/ai-assist/jsonResponse.js +149 -0
  6. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  7. package/dist/packlets/crypto-utils/keystore/keyStore.js +81 -0
  8. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
  9. package/dist/packlets/crypto-utils/model.js.map +1 -1
  10. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +9 -1
  11. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -1
  12. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  13. package/dist/packlets/csv/csvFileHelpers.js.map +1 -1
  14. package/dist/packlets/csv/csvHelpers.js +14 -0
  15. package/dist/packlets/csv/csvHelpers.js.map +1 -1
  16. package/dist/packlets/csv/index.browser.js +1 -3
  17. package/dist/packlets/csv/index.browser.js.map +1 -1
  18. package/dist/packlets/record-jar/index.browser.js +1 -3
  19. package/dist/packlets/record-jar/index.browser.js.map +1 -1
  20. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  21. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -1
  22. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  23. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -1
  24. package/dist/ts-extras.d.ts +239 -5
  25. package/lib/packlets/ai-assist/index.d.ts +2 -0
  26. package/lib/packlets/ai-assist/index.d.ts.map +1 -1
  27. package/lib/packlets/ai-assist/index.js +7 -1
  28. package/lib/packlets/ai-assist/index.js.map +1 -1
  29. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  30. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  31. package/lib/packlets/ai-assist/jsonCompletion.js +99 -0
  32. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  33. package/lib/packlets/ai-assist/jsonResponse.d.ts +91 -0
  34. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  35. package/lib/packlets/ai-assist/jsonResponse.js +154 -0
  36. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  37. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +43 -1
  38. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -1
  39. package/lib/packlets/crypto-utils/keystore/keyStore.js +81 -0
  40. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -1
  41. package/lib/packlets/crypto-utils/model.d.ts +10 -1
  42. package/lib/packlets/crypto-utils/model.d.ts.map +1 -1
  43. package/lib/packlets/crypto-utils/model.js.map +1 -1
  44. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +7 -1
  45. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -1
  46. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +8 -0
  47. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -1
  48. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  49. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -1
  50. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  51. package/lib/packlets/csv/csvFileHelpers.js.map +1 -1
  52. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  53. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -1
  54. package/lib/packlets/csv/csvHelpers.js +15 -0
  55. package/lib/packlets/csv/csvHelpers.js.map +1 -1
  56. package/lib/packlets/csv/index.browser.d.ts +0 -1
  57. package/lib/packlets/csv/index.browser.d.ts.map +1 -1
  58. package/lib/packlets/csv/index.browser.js +1 -5
  59. package/lib/packlets/csv/index.browser.js.map +1 -1
  60. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  61. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -1
  62. package/lib/packlets/record-jar/index.browser.js +1 -5
  63. package/lib/packlets/record-jar/index.browser.js.map +1 -1
  64. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  65. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -1
  66. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  67. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -1
  68. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  69. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -1
  70. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  71. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -1
  72. package/package.json +7 -7
@@ -6,6 +6,7 @@ import { Hash as Hash_2 } from '@fgv/ts-utils';
6
6
  import { JsonValue } from '@fgv/ts-json-base';
7
7
  import { Logging } from '@fgv/ts-utils';
8
8
  import { Result } from '@fgv/ts-utils';
9
+ import { Uuid } from '@fgv/ts-utils';
9
10
  import { Validator } from '@fgv/ts-utils';
10
11
 
11
12
  /**
@@ -87,7 +88,17 @@ declare namespace AiAssist {
87
88
  aiAssistSettings,
88
89
  modelSpecKey,
89
90
  modelSpec,
90
- resolveEffectiveTools
91
+ resolveEffectiveTools,
92
+ extractJsonText,
93
+ fencedStringifiedJson,
94
+ IFencedStringifiedJsonExtractorOptions,
95
+ IFencedStringifiedJsonOptions,
96
+ JsonTextExtractor,
97
+ generateJsonCompletion,
98
+ SMART_JSON_PROMPT_HINT,
99
+ IGenerateJsonCompletionParams,
100
+ IGenerateJsonCompletionResult,
101
+ JsonPromptHint
91
102
  }
92
103
  }
93
104
  export { AiAssist }
@@ -520,9 +531,9 @@ export { CryptoUtils }
520
531
  declare namespace Csv {
521
532
  export {
522
533
  parseCsvString,
534
+ readCsvFromTree,
523
535
  CsvOptions,
524
- readCsvFileSync,
525
- readCsvFromTree
536
+ readCsvFileSync
526
537
  }
527
538
  }
528
539
  export { Csv }
@@ -768,6 +779,54 @@ declare class ExtendedArray<T> extends Array<T> {
768
779
  */
769
780
  declare function extendedArrayOf<T, TC = undefined>(label: string, converter: Converter<T, TC>, onError?: Conversion.OnError): Converter<ExtendedArray<T>, TC>;
770
781
 
782
+ /**
783
+ * Default {@link AiAssist.JsonTextExtractor | extractor} for LLM responses. Tolerates:
784
+ *
785
+ * - Leading/trailing whitespace and a leading byte-order mark.
786
+ * - Markdown code fences (with or without a language tag).
787
+ * - Conversational preamble before the first `{` or `[`.
788
+ * - Trailing prose after the matched closing `}` or `]`.
789
+ *
790
+ * Out of scope: repairing malformed JSON, handling smart quotes, etc.
791
+ *
792
+ * @param text - Raw model output.
793
+ * @returns A `Result<string>` containing the JSON-shaped substring, or a
794
+ * `Failure` if no JSON-shaped substring was found.
795
+ * @public
796
+ */
797
+ declare const extractJsonText: JsonTextExtractor;
798
+
799
+ /**
800
+ * Creates a `Converter` that accepts raw LLM response text, runs it through a
801
+ * tolerant extractor (default: {@link AiAssist.extractJsonText}), parses the
802
+ * extracted substring as JSON, and applies an optional inner converter or
803
+ * validator.
804
+ *
805
+ * @example
806
+ * ```ts
807
+ * const converter = fencedStringifiedJson({ inner: myShapeConverter });
808
+ * const result = converter.convert(llmText); // Result<MyShape>
809
+ * ```
810
+ *
811
+ * @param options - Optional extractor; omit to keep the default. Without an
812
+ * `inner` step, the converter resolves to the parsed `JsonValue`.
813
+ * @returns A `Converter<JsonValue>`.
814
+ * @public
815
+ */
816
+ declare function fencedStringifiedJson(options?: IFencedStringifiedJsonExtractorOptions): Converter<JsonValue>;
817
+
818
+ /**
819
+ * Creates a `Converter` that accepts raw LLM response text, runs it through a
820
+ * tolerant extractor (default: {@link AiAssist.extractJsonText}), parses the
821
+ * extracted substring as JSON, and applies the supplied inner converter or
822
+ * validator.
823
+ *
824
+ * @param options - Required `inner` converter/validator and optional extractor.
825
+ * @returns A `Converter<T>`.
826
+ * @public
827
+ */
828
+ declare function fencedStringifiedJson<T>(options: IFencedStringifiedJsonOptions<T>): Converter<T>;
829
+
771
830
  /**
772
831
  * Formats a list of items using the supplied template and formatter, one result
773
832
  * per output line.
@@ -859,6 +918,27 @@ declare const GCM_AUTH_TAG_SIZE: number;
859
918
  */
860
919
  declare const GCM_IV_SIZE: number;
861
920
 
921
+ /**
922
+ * Calls {@link AiAssist.callProviderCompletion}, then runs the response text
923
+ * through a tolerant JSON converter (default:
924
+ * {@link AiAssist.fencedStringifiedJson}) and the caller's
925
+ * `converter`/`validator`. Returns the validated value plus the raw text and
926
+ * underlying completion response for diagnostics.
927
+ *
928
+ * @remarks
929
+ * The default smart prompt hint asks the model to emit raw JSON. The read-side
930
+ * extractor still tolerates fences and prose, so models that ignore the hint
931
+ * are still handled.
932
+ *
933
+ * Either `converter` or `jsonConverter` must be provided; passing both lets
934
+ * `jsonConverter` win.
935
+ *
936
+ * @param params - Provider parameters plus JSON validation options.
937
+ * @returns The validated value, the raw text, and the underlying response.
938
+ * @public
939
+ */
940
+ declare function generateJsonCompletion<T>(params: IGenerateJsonCompletionParams<T>): Promise<Result<IGenerateJsonCompletionResult<T>>>;
941
+
862
942
  /**
863
943
  * Get a provider descriptor by id.
864
944
  * @param id - The provider identifier
@@ -1540,6 +1620,15 @@ declare interface ICryptoProvider {
1540
1620
  * @returns Success with random bytes, or Failure with error
1541
1621
  */
1542
1622
  generateRandomBytes(length: number): Result<Uint8Array>;
1623
+ /**
1624
+ * Generates a cryptographically random UUIDv4 using the provider's
1625
+ * underlying source of randomness. The default Node and browser
1626
+ * implementations delegate to `globalThis.crypto.randomUUID`;
1627
+ * deterministic providers (e.g. test stubs) may override to produce
1628
+ * reproducible values.
1629
+ * @returns Success with a canonical UUID, or Failure with error.
1630
+ */
1631
+ generateUuid(): Result<Uuid>;
1543
1632
  /**
1544
1633
  * Encodes binary data to base64 string.
1545
1634
  * @param data - Binary data to encode
@@ -1757,6 +1846,70 @@ declare interface IEncryptionResult {
1757
1846
  readonly encryptedData: Uint8Array;
1758
1847
  }
1759
1848
 
1849
+ /**
1850
+ * Options shared by every {@link AiAssist.fencedStringifiedJson} call.
1851
+ * @public
1852
+ */
1853
+ declare interface IFencedStringifiedJsonExtractorOptions {
1854
+ /**
1855
+ * Optional pre-parse extractor. Defaults to {@link AiAssist.extractJsonText}.
1856
+ * Provide a custom extractor to handle response shapes the default does not
1857
+ * understand.
1858
+ */
1859
+ readonly extractor?: JsonTextExtractor;
1860
+ }
1861
+
1862
+ /**
1863
+ * Options for the validating overload of {@link AiAssist.fencedStringifiedJson}.
1864
+ * `inner` is required so the typed `Converter<T>` return value can never lie
1865
+ * about the runtime shape.
1866
+ * @public
1867
+ */
1868
+ declare interface IFencedStringifiedJsonOptions<T> extends IFencedStringifiedJsonExtractorOptions {
1869
+ /** Inner converter or validator applied to the parsed JSON value. */
1870
+ readonly inner: Converter<T> | Validator<T>;
1871
+ }
1872
+
1873
+ /**
1874
+ * Parameters for {@link AiAssist.generateJsonCompletion}. Extends
1875
+ * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.
1876
+ * @public
1877
+ */
1878
+ declare interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {
1879
+ /**
1880
+ * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed
1881
+ * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}
1882
+ * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is
1883
+ * provided.
1884
+ */
1885
+ readonly converter?: Converter<T> | Validator<T>;
1886
+ /**
1887
+ * Full string-to-`T` pipeline override. When supplied, takes precedence over
1888
+ * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the
1889
+ * caller plug in a custom extractor or skip the default fence tolerance
1890
+ * entirely.
1891
+ */
1892
+ readonly jsonConverter?: Converter<T>;
1893
+ /**
1894
+ * Controls the optional system-prompt augmentation. Defaults to `'smart'`.
1895
+ * Pass `'none'` to disable, or a string to append custom guidance.
1896
+ */
1897
+ readonly promptHint?: JsonPromptHint;
1898
+ }
1899
+
1900
+ /**
1901
+ * Successful result of {@link AiAssist.generateJsonCompletion}.
1902
+ * @public
1903
+ */
1904
+ declare interface IGenerateJsonCompletionResult<T> {
1905
+ /** The validated JSON value. */
1906
+ readonly value: T;
1907
+ /** The raw response text returned by the provider. */
1908
+ readonly raw: string;
1909
+ /** The full underlying completion response. */
1910
+ readonly response: IAiCompletionResponse;
1911
+ }
1912
+
1760
1913
  /**
1761
1914
  * Options for importing raw key material via {@link KeyStore.importSecret}.
1762
1915
  * Extends {@link IImportSecretOptions} with a type classification.
@@ -2575,6 +2728,31 @@ declare interface JarRecordParserOptions {
2575
2728
  readonly fixedContinuationSize?: number;
2576
2729
  }
2577
2730
 
2731
+ /**
2732
+ * Controls the optional system-prompt augmentation applied by
2733
+ * {@link AiAssist.generateJsonCompletion}.
2734
+ *
2735
+ * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.
2736
+ * - `'none'`: do not modify the prompt.
2737
+ * - A string: append the supplied text verbatim.
2738
+ *
2739
+ * @remarks
2740
+ * The `string & {}` branch is the standard TypeScript trick that prevents
2741
+ * the literal members from being widened away — callers still get
2742
+ * autocomplete for `'smart'` and `'none'` while accepting any string.
2743
+ *
2744
+ * @public
2745
+ */
2746
+ declare type JsonPromptHint = 'smart' | 'none' | (string & {});
2747
+
2748
+ /**
2749
+ * A function that pulls a JSON-shaped substring out of arbitrary model text.
2750
+ * Implementations strip whatever wrappers the model added (fences, preamble,
2751
+ * trailing prose) and return the JSON-shaped substring ready for `JSON.parse`.
2752
+ * @public
2753
+ */
2754
+ declare type JsonTextExtractor = (text: string) => Result<string>;
2755
+
2578
2756
  /**
2579
2757
  * In-place shape check for a JSON Web Key. Asserts only that the input is a
2580
2758
  * non-array object whose `kty` discriminator is a string; every other JWK
@@ -2882,6 +3060,41 @@ declare class KeyStore_2 implements IEncryptionProvider {
2882
3060
  * @public
2883
3061
  */
2884
3062
  addSecretFromPassword(name: string, password: string, options?: IAddSecretFromPasswordOptions): Promise<Result<IAddSecretFromPasswordResult>>;
3063
+ /**
3064
+ * Verifies that a candidate password derives the same key material currently
3065
+ * stored under `name`, using the supplied
3066
+ * {@link CryptoUtils.IKeyDerivationParams | key derivation parameters}.
3067
+ *
3068
+ * The keystore does not persist per-slot key derivation parameters with the
3069
+ * entry — callers receive them from `addSecretFromPassword` and store them
3070
+ * alongside the encrypted artifact (or wherever else makes sense). Pass
3071
+ * those same parameters here for verification.
3072
+ *
3073
+ * Re-derives a key from `password` + `keyDerivation`, then compares it to
3074
+ * the stored key material in constant time. Restricted to entries of type
3075
+ * `'encryption-key'` — the type produced by `addSecretFromPassword`. Other
3076
+ * symmetric types (`'api-key'`) and asymmetric entries are rejected so
3077
+ * the boolean result reflects "this slot accepts this password" rather
3078
+ * than an incidental byte-equality match against unrelated material.
3079
+ *
3080
+ * Note: the keystore does not currently flag whether an `'encryption-key'`
3081
+ * entry was actually password-derived (vs. random via `addSecret` or raw
3082
+ * via `importSecret`). A `true` result therefore means "the candidate
3083
+ * password produces the same 32 bytes currently stored", which is what
3084
+ * the equivalent consumer-side helper (`verifyGatePassword`) already
3085
+ * implies for entries it manages.
3086
+ *
3087
+ * @param name - Name of the secret to verify against
3088
+ * @param password - Candidate password to test
3089
+ * @param keyDerivation - The key derivation parameters returned by
3090
+ * `addSecretFromPassword` when the secret was created. Only
3091
+ * `kdf: 'pbkdf2'` is supported.
3092
+ * @returns Success(true) when the candidate matches the stored key,
3093
+ * Success(false) when it does not, Failure if locked, secret missing,
3094
+ * wrong type, unsupported `kdf`, or key derivation fails
3095
+ * @public
3096
+ */
3097
+ verifySecretFromPassword(name: string, password: string, keyDerivation: IKeyDerivationParams): Promise<Result<boolean>>;
2885
3098
  /**
2886
3099
  * Removes a secret by name. Vault-first: the in-memory vault entry is dropped
2887
3100
  * before any storage cleanup runs. For asymmetric-keypair entries, best-effort
@@ -3028,6 +3241,13 @@ declare class KeyStore_2 implements IEncryptionProvider {
3028
3241
  * @returns A warning string if storage cleanup failed, otherwise undefined.
3029
3242
  */
3030
3243
  private _releaseEntryResources;
3244
+ /**
3245
+ * Constant-time byte comparison. Returns false immediately for length
3246
+ * mismatch (length is not secret); for equal-length inputs, walks the full
3247
+ * buffer accumulating differences via XOR so the running time does not leak
3248
+ * the position of the first differing byte.
3249
+ */
3250
+ private static _timingSafeEqual;
3031
3251
  /**
3032
3252
  * Mints a fresh UUID v4 storage handle using the crypto provider's
3033
3253
  * {@link CryptoUtils.ICryptoProvider.generateRandomBytes | generateRandomBytes}.
@@ -3346,6 +3566,12 @@ declare class NodeCryptoProvider implements ICryptoProvider {
3346
3566
  * @returns Success with random bytes, or Failure with error
3347
3567
  */
3348
3568
  generateRandomBytes(length: number): Result<Uint8Array>;
3569
+ /**
3570
+ * Generates a cryptographically random UUIDv4 via the platform Web Crypto API.
3571
+ * @returns `Success` with the generated UUID, or `Failure` if the runtime
3572
+ * does not expose `globalThis.crypto.randomUUID`.
3573
+ */
3574
+ generateUuid(): Result<Uuid>;
3349
3575
  /**
3350
3576
  * Encodes binary data to base64 string.
3351
3577
  * @param data - Binary data to encode
@@ -3606,11 +3832,11 @@ declare function readRecordJarFromTree(fileTree: FileTree.FileTree, filePath: st
3606
3832
  declare namespace RecordJar {
3607
3833
  export {
3608
3834
  parseRecordJarLines,
3835
+ readRecordJarFromTree,
3609
3836
  JarRecord,
3610
3837
  JarFieldPicker,
3611
3838
  JarRecordParserOptions,
3612
- readRecordJarFileSync,
3613
- readRecordJarFromTree
3839
+ readRecordJarFileSync
3614
3840
  }
3615
3841
  }
3616
3842
  export { RecordJar }
@@ -3670,6 +3896,14 @@ declare function resolveModel(spec: ModelSpec, context?: string): string;
3670
3896
  */
3671
3897
  declare type SecretProvider = (secretName: string) => Promise<Result<Uint8Array>>;
3672
3898
 
3899
+ /**
3900
+ * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}
3901
+ * is `'smart'` (the default). Designed to discourage code fences and prose in
3902
+ * the model's response while still tolerating them via the read-side extractor.
3903
+ * @public
3904
+ */
3905
+ declare const SMART_JSON_PROMPT_HINT: string;
3906
+
3673
3907
  /**
3674
3908
  * Whether a provider declares any image-generation capability at all.
3675
3909
  *
@@ -8,4 +8,6 @@ export { callProviderCompletion, callProxiedCompletion, callProviderImageGenerat
8
8
  export { callProviderCompletionStream, callProxiedCompletionStream, type IProviderCompletionStreamParams } from './streamingClient';
9
9
  export { aiProviderId, aiServerToolType, aiWebSearchToolConfig, aiServerToolConfig, aiToolEnablement, aiAssistProviderConfig, aiAssistSettings, modelSpecKey, modelSpec } from './converters';
10
10
  export { resolveEffectiveTools } from './toolFormats';
11
+ export { extractJsonText, fencedStringifiedJson, type IFencedStringifiedJsonExtractorOptions, type IFencedStringifiedJsonOptions, type JsonTextExtractor } from './jsonResponse';
12
+ export { generateJsonCompletion, SMART_JSON_PROMPT_HINT, type IGenerateJsonCompletionParams, type IGenerateJsonCompletionResult, type JsonPromptHint } from './jsonCompletion';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,QAAQ,EACR,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAChC,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,KAAK,+BAA+B,EACrC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,QAAQ,EACR,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAChC,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,KAAK,+BAA+B,EACrC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,KAAK,sCAAsC,EAC3C,KAAK,6BAA6B,EAClC,KAAK,iBAAiB,EACvB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,6BAA6B,EAClC,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.resolveEffectiveTools = exports.modelSpec = exports.modelSpecKey = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.aiToolEnablement = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = exports.callProxiedCompletionStream = exports.callProviderCompletionStream = exports.callProxiedListModels = exports.callProviderListModels = exports.callProxiedImageGeneration = exports.callProviderImageGeneration = exports.callProxiedCompletion = exports.callProviderCompletion = exports.DEFAULT_MODEL_CAPABILITY_CONFIG = exports.supportsImageGeneration = exports.resolveImageCapability = exports.getProviderDescriptor = exports.getProviderDescriptors = exports.allProviderIds = exports.toDataUrl = exports.resolveModel = exports.MODEL_SPEC_BASE_KEY = exports.allModelSpecKeys = exports.DEFAULT_AI_ASSIST = exports.AiPrompt = void 0;
7
+ exports.SMART_JSON_PROMPT_HINT = exports.generateJsonCompletion = exports.fencedStringifiedJson = exports.extractJsonText = exports.resolveEffectiveTools = exports.modelSpec = exports.modelSpecKey = exports.aiAssistSettings = exports.aiAssistProviderConfig = exports.aiToolEnablement = exports.aiServerToolConfig = exports.aiWebSearchToolConfig = exports.aiServerToolType = exports.aiProviderId = exports.callProxiedCompletionStream = exports.callProviderCompletionStream = exports.callProxiedListModels = exports.callProviderListModels = exports.callProxiedImageGeneration = exports.callProviderImageGeneration = exports.callProxiedCompletion = exports.callProviderCompletion = exports.DEFAULT_MODEL_CAPABILITY_CONFIG = exports.supportsImageGeneration = exports.resolveImageCapability = exports.getProviderDescriptor = exports.getProviderDescriptors = exports.allProviderIds = exports.toDataUrl = exports.resolveModel = exports.MODEL_SPEC_BASE_KEY = exports.allModelSpecKeys = exports.DEFAULT_AI_ASSIST = exports.AiPrompt = void 0;
8
8
  var model_1 = require("./model");
9
9
  Object.defineProperty(exports, "AiPrompt", { enumerable: true, get: function () { return model_1.AiPrompt; } });
10
10
  Object.defineProperty(exports, "DEFAULT_AI_ASSIST", { enumerable: true, get: function () { return model_1.DEFAULT_AI_ASSIST; } });
@@ -41,4 +41,10 @@ Object.defineProperty(exports, "modelSpecKey", { enumerable: true, get: function
41
41
  Object.defineProperty(exports, "modelSpec", { enumerable: true, get: function () { return converters_1.modelSpec; } });
42
42
  var toolFormats_1 = require("./toolFormats");
43
43
  Object.defineProperty(exports, "resolveEffectiveTools", { enumerable: true, get: function () { return toolFormats_1.resolveEffectiveTools; } });
44
+ var jsonResponse_1 = require("./jsonResponse");
45
+ Object.defineProperty(exports, "extractJsonText", { enumerable: true, get: function () { return jsonResponse_1.extractJsonText; } });
46
+ Object.defineProperty(exports, "fencedStringifiedJson", { enumerable: true, get: function () { return jsonResponse_1.fencedStringifiedJson; } });
47
+ var jsonCompletion_1 = require("./jsonCompletion");
48
+ Object.defineProperty(exports, "generateJsonCompletion", { enumerable: true, get: function () { return jsonCompletion_1.generateJsonCompletion; } });
49
+ Object.defineProperty(exports, "SMART_JSON_PROMPT_HINT", { enumerable: true, get: function () { return jsonCompletion_1.SMART_JSON_PROMPT_HINT; } });
44
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAuCiB;AAtCf,iGAAA,QAAQ,OAAA;AAeR,0GAAA,iBAAiB,OAAA;AAmBjB,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,qGAAA,YAAY,OAAA;AACZ,kGAAA,SAAS,OAAA;AAGX,uCAOoB;AANlB,0GAAA,cAAc,OAAA;AACd,kHAAA,sBAAsB,OAAA;AACtB,iHAAA,qBAAqB,OAAA;AACrB,kHAAA,sBAAsB,OAAA;AACtB,mHAAA,uBAAuB,OAAA;AACvB,2HAAA,+BAA+B,OAAA;AAGjC,yCAUqB;AATnB,mHAAA,sBAAsB,OAAA;AACtB,kHAAA,qBAAqB,OAAA;AACrB,wHAAA,2BAA2B,OAAA;AAC3B,uHAAA,0BAA0B,OAAA;AAC1B,mHAAA,sBAAsB,OAAA;AACtB,kHAAA,qBAAqB,OAAA;AAMvB,qDAI2B;AAHzB,+HAAA,4BAA4B,OAAA;AAC5B,8HAAA,2BAA2B,OAAA;AAI7B,2CAUsB;AATpB,0GAAA,YAAY,OAAA;AACZ,8GAAA,gBAAgB,OAAA;AAChB,mHAAA,qBAAqB,OAAA;AACrB,gHAAA,kBAAkB,OAAA;AAClB,8GAAA,gBAAgB,OAAA;AAChB,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAChB,0GAAA,YAAY,OAAA;AACZ,uGAAA,SAAS,OAAA;AAGX,6CAAsD;AAA7C,oHAAA,qBAAqB,OAAA","sourcesContent":["/**\n * AI assist packlet - provider registry, prompt class, settings, and API client.\n * @packageDocumentation\n */\n\nexport {\n AiPrompt,\n type AiModelCapability,\n type AiProviderId,\n type AiServerToolType,\n type AiServerToolConfig,\n type IAiWebSearchToolConfig,\n type IAiToolEnablement,\n type IAiCompletionResponse,\n type IChatMessage,\n type AiApiFormat,\n type AiImageApiFormat,\n type IAiImageModelCapability,\n type IAiProviderDescriptor,\n type IAiAssistProviderConfig,\n type IAiAssistSettings,\n DEFAULT_AI_ASSIST,\n type IAiAssistKeyStore,\n type IAiImageAttachment,\n type IAiImageData,\n type IAiImageGenerationOptions,\n type IAiImageGenerationParams,\n type IAiGeneratedImage,\n type IAiImageGenerationResponse,\n type IAiModelCapabilityRule,\n type IAiModelCapabilityConfig,\n type IAiModelInfo,\n type IAiStreamEvent,\n type IAiStreamTextDelta,\n type IAiStreamToolEvent,\n type IAiStreamDone,\n type IAiStreamError,\n type ModelSpec,\n type ModelSpecKey,\n type IModelSpecMap,\n allModelSpecKeys,\n MODEL_SPEC_BASE_KEY,\n resolveModel,\n toDataUrl\n} from './model';\n\nexport {\n allProviderIds,\n getProviderDescriptors,\n getProviderDescriptor,\n resolveImageCapability,\n supportsImageGeneration,\n DEFAULT_MODEL_CAPABILITY_CONFIG\n} from './registry';\n\nexport {\n callProviderCompletion,\n callProxiedCompletion,\n callProviderImageGeneration,\n callProxiedImageGeneration,\n callProviderListModels,\n callProxiedListModels,\n type IProviderCompletionParams,\n type IProviderImageGenerationParams,\n type IProviderListModelsParams\n} from './apiClient';\n\nexport {\n callProviderCompletionStream,\n callProxiedCompletionStream,\n type IProviderCompletionStreamParams\n} from './streamingClient';\n\nexport {\n aiProviderId,\n aiServerToolType,\n aiWebSearchToolConfig,\n aiServerToolConfig,\n aiToolEnablement,\n aiAssistProviderConfig,\n aiAssistSettings,\n modelSpecKey,\n modelSpec\n} from './converters';\n\nexport { resolveEffectiveTools } from './toolFormats';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAuCiB;AAtCf,iGAAA,QAAQ,OAAA;AAeR,0GAAA,iBAAiB,OAAA;AAmBjB,yGAAA,gBAAgB,OAAA;AAChB,4GAAA,mBAAmB,OAAA;AACnB,qGAAA,YAAY,OAAA;AACZ,kGAAA,SAAS,OAAA;AAGX,uCAOoB;AANlB,0GAAA,cAAc,OAAA;AACd,kHAAA,sBAAsB,OAAA;AACtB,iHAAA,qBAAqB,OAAA;AACrB,kHAAA,sBAAsB,OAAA;AACtB,mHAAA,uBAAuB,OAAA;AACvB,2HAAA,+BAA+B,OAAA;AAGjC,yCAUqB;AATnB,mHAAA,sBAAsB,OAAA;AACtB,kHAAA,qBAAqB,OAAA;AACrB,wHAAA,2BAA2B,OAAA;AAC3B,uHAAA,0BAA0B,OAAA;AAC1B,mHAAA,sBAAsB,OAAA;AACtB,kHAAA,qBAAqB,OAAA;AAMvB,qDAI2B;AAHzB,+HAAA,4BAA4B,OAAA;AAC5B,8HAAA,2BAA2B,OAAA;AAI7B,2CAUsB;AATpB,0GAAA,YAAY,OAAA;AACZ,8GAAA,gBAAgB,OAAA;AAChB,mHAAA,qBAAqB,OAAA;AACrB,gHAAA,kBAAkB,OAAA;AAClB,8GAAA,gBAAgB,OAAA;AAChB,oHAAA,sBAAsB,OAAA;AACtB,8GAAA,gBAAgB,OAAA;AAChB,0GAAA,YAAY,OAAA;AACZ,uGAAA,SAAS,OAAA;AAGX,6CAAsD;AAA7C,oHAAA,qBAAqB,OAAA;AAE9B,+CAMwB;AALtB,+GAAA,eAAe,OAAA;AACf,qHAAA,qBAAqB,OAAA;AAMvB,mDAM0B;AALxB,wHAAA,sBAAsB,OAAA;AACtB,wHAAA,sBAAsB,OAAA","sourcesContent":["/**\n * AI assist packlet - provider registry, prompt class, settings, and API client.\n * @packageDocumentation\n */\n\nexport {\n AiPrompt,\n type AiModelCapability,\n type AiProviderId,\n type AiServerToolType,\n type AiServerToolConfig,\n type IAiWebSearchToolConfig,\n type IAiToolEnablement,\n type IAiCompletionResponse,\n type IChatMessage,\n type AiApiFormat,\n type AiImageApiFormat,\n type IAiImageModelCapability,\n type IAiProviderDescriptor,\n type IAiAssistProviderConfig,\n type IAiAssistSettings,\n DEFAULT_AI_ASSIST,\n type IAiAssistKeyStore,\n type IAiImageAttachment,\n type IAiImageData,\n type IAiImageGenerationOptions,\n type IAiImageGenerationParams,\n type IAiGeneratedImage,\n type IAiImageGenerationResponse,\n type IAiModelCapabilityRule,\n type IAiModelCapabilityConfig,\n type IAiModelInfo,\n type IAiStreamEvent,\n type IAiStreamTextDelta,\n type IAiStreamToolEvent,\n type IAiStreamDone,\n type IAiStreamError,\n type ModelSpec,\n type ModelSpecKey,\n type IModelSpecMap,\n allModelSpecKeys,\n MODEL_SPEC_BASE_KEY,\n resolveModel,\n toDataUrl\n} from './model';\n\nexport {\n allProviderIds,\n getProviderDescriptors,\n getProviderDescriptor,\n resolveImageCapability,\n supportsImageGeneration,\n DEFAULT_MODEL_CAPABILITY_CONFIG\n} from './registry';\n\nexport {\n callProviderCompletion,\n callProxiedCompletion,\n callProviderImageGeneration,\n callProxiedImageGeneration,\n callProviderListModels,\n callProxiedListModels,\n type IProviderCompletionParams,\n type IProviderImageGenerationParams,\n type IProviderListModelsParams\n} from './apiClient';\n\nexport {\n callProviderCompletionStream,\n callProxiedCompletionStream,\n type IProviderCompletionStreamParams\n} from './streamingClient';\n\nexport {\n aiProviderId,\n aiServerToolType,\n aiWebSearchToolConfig,\n aiServerToolConfig,\n aiToolEnablement,\n aiAssistProviderConfig,\n aiAssistSettings,\n modelSpecKey,\n modelSpec\n} from './converters';\n\nexport { resolveEffectiveTools } from './toolFormats';\n\nexport {\n extractJsonText,\n fencedStringifiedJson,\n type IFencedStringifiedJsonExtractorOptions,\n type IFencedStringifiedJsonOptions,\n type JsonTextExtractor\n} from './jsonResponse';\n\nexport {\n generateJsonCompletion,\n SMART_JSON_PROMPT_HINT,\n type IGenerateJsonCompletionParams,\n type IGenerateJsonCompletionResult,\n type JsonPromptHint\n} from './jsonCompletion';\n"]}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * `generateJsonCompletion<T>` — request a JSON-shaped completion from any
3
+ * provider supported by AiAssist and validate it against a caller-supplied
4
+ * `Converter<T>` or `Validator<T>`. Wraps fence/preamble tolerance + parsing +
5
+ * validation into a single call so consumers don't reinvent the pipeline.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { type Converter, Result, type Validator } from '@fgv/ts-utils';
10
+ import { type IProviderCompletionParams } from './apiClient';
11
+ import { type IAiCompletionResponse } from './model';
12
+ /**
13
+ * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}
14
+ * is `'smart'` (the default). Designed to discourage code fences and prose in
15
+ * the model's response while still tolerating them via the read-side extractor.
16
+ * @public
17
+ */
18
+ export declare const SMART_JSON_PROMPT_HINT: string;
19
+ /**
20
+ * Controls the optional system-prompt augmentation applied by
21
+ * {@link AiAssist.generateJsonCompletion}.
22
+ *
23
+ * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.
24
+ * - `'none'`: do not modify the prompt.
25
+ * - A string: append the supplied text verbatim.
26
+ *
27
+ * @remarks
28
+ * The `string & {}` branch is the standard TypeScript trick that prevents
29
+ * the literal members from being widened away — callers still get
30
+ * autocomplete for `'smart'` and `'none'` while accepting any string.
31
+ *
32
+ * @public
33
+ */
34
+ export type JsonPromptHint = 'smart' | 'none' | (string & {});
35
+ /**
36
+ * Parameters for {@link AiAssist.generateJsonCompletion}. Extends
37
+ * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.
38
+ * @public
39
+ */
40
+ export interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {
41
+ /**
42
+ * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed
43
+ * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}
44
+ * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is
45
+ * provided.
46
+ */
47
+ readonly converter?: Converter<T> | Validator<T>;
48
+ /**
49
+ * Full string-to-`T` pipeline override. When supplied, takes precedence over
50
+ * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the
51
+ * caller plug in a custom extractor or skip the default fence tolerance
52
+ * entirely.
53
+ */
54
+ readonly jsonConverter?: Converter<T>;
55
+ /**
56
+ * Controls the optional system-prompt augmentation. Defaults to `'smart'`.
57
+ * Pass `'none'` to disable, or a string to append custom guidance.
58
+ */
59
+ readonly promptHint?: JsonPromptHint;
60
+ }
61
+ /**
62
+ * Successful result of {@link AiAssist.generateJsonCompletion}.
63
+ * @public
64
+ */
65
+ export interface IGenerateJsonCompletionResult<T> {
66
+ /** The validated JSON value. */
67
+ readonly value: T;
68
+ /** The raw response text returned by the provider. */
69
+ readonly raw: string;
70
+ /** The full underlying completion response. */
71
+ readonly response: IAiCompletionResponse;
72
+ }
73
+ /**
74
+ * Calls {@link AiAssist.callProviderCompletion}, then runs the response text
75
+ * through a tolerant JSON converter (default:
76
+ * {@link AiAssist.fencedStringifiedJson}) and the caller's
77
+ * `converter`/`validator`. Returns the validated value plus the raw text and
78
+ * underlying completion response for diagnostics.
79
+ *
80
+ * @remarks
81
+ * The default smart prompt hint asks the model to emit raw JSON. The read-side
82
+ * extractor still tolerates fences and prose, so models that ignore the hint
83
+ * are still handled.
84
+ *
85
+ * Either `converter` or `jsonConverter` must be provided; passing both lets
86
+ * `jsonConverter` win.
87
+ *
88
+ * @param params - Provider parameters plus JSON validation options.
89
+ * @returns The validated value, the raw text, and the underlying response.
90
+ * @public
91
+ */
92
+ export declare function generateJsonCompletion<T>(params: IGenerateJsonCompletionParams<T>): Promise<Result<IGenerateJsonCompletionResult<T>>>;
93
+ //# sourceMappingURL=jsonCompletion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonCompletion.d.ts","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":"AAoBA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAQ,MAAM,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtF,OAAO,EAA0B,KAAK,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAErF,OAAO,EAAY,KAAK,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAE2C,CAAC;AAEjF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,6BAA6B,CAAC,CAAC,CAAE,SAAQ,yBAAyB;IACjF;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAEtC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,6BAA6B,CAAC,CAAC;IAC9C,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC;CAC1C;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,MAAM,EAAE,6BAA6B,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CAoBnD"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ var __rest = (this && this.__rest) || function (s, e) {
22
+ var t = {};
23
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
24
+ t[p] = s[p];
25
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
26
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
27
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
28
+ t[p[i]] = s[p[i]];
29
+ }
30
+ return t;
31
+ };
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.SMART_JSON_PROMPT_HINT = void 0;
34
+ exports.generateJsonCompletion = generateJsonCompletion;
35
+ /**
36
+ * `generateJsonCompletion<T>` — request a JSON-shaped completion from any
37
+ * provider supported by AiAssist and validate it against a caller-supplied
38
+ * `Converter<T>` or `Validator<T>`. Wraps fence/preamble tolerance + parsing +
39
+ * validation into a single call so consumers don't reinvent the pipeline.
40
+ *
41
+ * @packageDocumentation
42
+ */
43
+ const ts_utils_1 = require("@fgv/ts-utils");
44
+ const apiClient_1 = require("./apiClient");
45
+ const jsonResponse_1 = require("./jsonResponse");
46
+ const model_1 = require("./model");
47
+ /**
48
+ * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}
49
+ * is `'smart'` (the default). Designed to discourage code fences and prose in
50
+ * the model's response while still tolerating them via the read-side extractor.
51
+ * @public
52
+ */
53
+ exports.SMART_JSON_PROMPT_HINT = 'Respond with raw JSON only — no Markdown code fences, no explanatory prose, ' +
54
+ 'no preamble or trailing commentary. The response must parse with JSON.parse.';
55
+ function applyPromptHint(prompt, hint) {
56
+ if (hint === 'none') {
57
+ return prompt;
58
+ }
59
+ const suffix = hint === 'smart' ? exports.SMART_JSON_PROMPT_HINT : hint;
60
+ const system = prompt.system.length > 0 ? `${prompt.system}\n\n${suffix}` : suffix;
61
+ return new model_1.AiPrompt(prompt.user, system, prompt.attachments);
62
+ }
63
+ /**
64
+ * Calls {@link AiAssist.callProviderCompletion}, then runs the response text
65
+ * through a tolerant JSON converter (default:
66
+ * {@link AiAssist.fencedStringifiedJson}) and the caller's
67
+ * `converter`/`validator`. Returns the validated value plus the raw text and
68
+ * underlying completion response for diagnostics.
69
+ *
70
+ * @remarks
71
+ * The default smart prompt hint asks the model to emit raw JSON. The read-side
72
+ * extractor still tolerates fences and prose, so models that ignore the hint
73
+ * are still handled.
74
+ *
75
+ * Either `converter` or `jsonConverter` must be provided; passing both lets
76
+ * `jsonConverter` win.
77
+ *
78
+ * @param params - Provider parameters plus JSON validation options.
79
+ * @returns The validated value, the raw text, and the underlying response.
80
+ * @public
81
+ */
82
+ async function generateJsonCompletion(params) {
83
+ const { converter, jsonConverter, promptHint = 'smart', prompt } = params, rest = __rest(params, ["converter", "jsonConverter", "promptHint", "prompt"]);
84
+ if (jsonConverter === undefined && converter === undefined) {
85
+ return (0, ts_utils_1.fail)('generateJsonCompletion: either converter or jsonConverter must be provided.');
86
+ }
87
+ const pipeline = jsonConverter !== null && jsonConverter !== void 0 ? jsonConverter : (0, jsonResponse_1.fencedStringifiedJson)({ inner: converter });
88
+ const augmentedPrompt = applyPromptHint(prompt, promptHint);
89
+ const response = await (0, apiClient_1.callProviderCompletion)(Object.assign(Object.assign({}, rest), { prompt: augmentedPrompt }));
90
+ if (response.isFailure()) {
91
+ return (0, ts_utils_1.fail)(response.message);
92
+ }
93
+ const completion = response.value;
94
+ return pipeline
95
+ .convert(completion.content)
96
+ .withErrorFormat((msg) => `generateJsonCompletion: ${msg}`)
97
+ .onSuccess((value) => (0, ts_utils_1.succeed)({ value, raw: completion.content, response: completion }));
98
+ }
99
+ //# sourceMappingURL=jsonCompletion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonCompletion.js","sourceRoot":"","sources":["../../../src/packlets/ai-assist/jsonCompletion.ts"],"names":[],"mappings":";AAAA,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AACxE,2DAA2D;AAC3D,EAAE;AACF,iFAAiF;AACjF,kDAAkD;AAClD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,gFAAgF;AAChF,gFAAgF;AAChF,YAAY;;;;;;;;;;;;;;AAkHZ,wDAsBC;AAtID;;;;;;;GAOG;AAEH,4CAAsF;AAEtF,2CAAqF;AACrF,iDAAuD;AACvD,mCAA+D;AAE/D;;;;;GAKG;AACU,QAAA,sBAAsB,GACjC,8EAA8E;IAC9E,8EAA8E,CAAC;AA6DjF,SAAS,eAAe,CAAC,MAAgB,EAAE,IAAoB;IAC7D,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,8BAAsB,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACnF,OAAO,IAAI,gBAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACI,KAAK,UAAU,sBAAsB,CAC1C,MAAwC;IAExC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,GAAG,OAAO,EAAE,MAAM,KAAc,MAAM,EAAf,IAAI,UAAK,MAAM,EAA5E,sDAAmE,CAAS,CAAC;IAEnF,IAAI,aAAa,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,IAAA,eAAI,EAAC,6EAA6E,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,QAAQ,GAAiB,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,IAAA,oCAAqB,EAAI,EAAE,KAAK,EAAE,SAAU,EAAE,CAAC,CAAC;IAChG,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,MAAM,IAAA,kCAAsB,kCAAM,IAAI,KAAE,MAAM,EAAE,eAAe,IAAG,CAAC;IACpF,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC;QACzB,OAAO,IAAA,eAAI,EAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC;IAElC,OAAO,QAAQ;SACZ,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;SAC3B,eAAe,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,2BAA2B,GAAG,EAAE,CAAC;SAC1D,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,kBAAO,EAAC,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n/**\n * `generateJsonCompletion<T>` — request a JSON-shaped completion from any\n * provider supported by AiAssist and validate it against a caller-supplied\n * `Converter<T>` or `Validator<T>`. Wraps fence/preamble tolerance + parsing +\n * validation into a single call so consumers don't reinvent the pipeline.\n *\n * @packageDocumentation\n */\n\nimport { type Converter, fail, Result, succeed, type Validator } from '@fgv/ts-utils';\n\nimport { callProviderCompletion, type IProviderCompletionParams } from './apiClient';\nimport { fencedStringifiedJson } from './jsonResponse';\nimport { AiPrompt, type IAiCompletionResponse } from './model';\n\n/**\n * Default system-prompt suffix appended when {@link AiAssist.IGenerateJsonCompletionParams.promptHint}\n * is `'smart'` (the default). Designed to discourage code fences and prose in\n * the model's response while still tolerating them via the read-side extractor.\n * @public\n */\nexport const SMART_JSON_PROMPT_HINT: string =\n 'Respond with raw JSON only — no Markdown code fences, no explanatory prose, ' +\n 'no preamble or trailing commentary. The response must parse with JSON.parse.';\n\n/**\n * Controls the optional system-prompt augmentation applied by\n * {@link AiAssist.generateJsonCompletion}.\n *\n * - `'smart'` (default): append {@link AiAssist.SMART_JSON_PROMPT_HINT}.\n * - `'none'`: do not modify the prompt.\n * - A string: append the supplied text verbatim.\n *\n * @remarks\n * The `string & {}` branch is the standard TypeScript trick that prevents\n * the literal members from being widened away — callers still get\n * autocomplete for `'smart'` and `'none'` while accepting any string.\n *\n * @public\n */\nexport type JsonPromptHint = 'smart' | 'none' | (string & {});\n\n/**\n * Parameters for {@link AiAssist.generateJsonCompletion}. Extends\n * {@link AiAssist.IProviderCompletionParams} with JSON-validation knobs.\n * @public\n */\nexport interface IGenerateJsonCompletionParams<T> extends IProviderCompletionParams {\n /**\n * Caller-supplied `Converter<T>` or `Validator<T>` applied to the parsed\n * JSON value. Wrapped internally in {@link AiAssist.fencedStringifiedJson}\n * unless {@link AiAssist.IGenerateJsonCompletionParams.jsonConverter} is\n * provided.\n */\n readonly converter?: Converter<T> | Validator<T>;\n\n /**\n * Full string-to-`T` pipeline override. When supplied, takes precedence over\n * {@link AiAssist.IGenerateJsonCompletionParams.converter} and lets the\n * caller plug in a custom extractor or skip the default fence tolerance\n * entirely.\n */\n readonly jsonConverter?: Converter<T>;\n\n /**\n * Controls the optional system-prompt augmentation. Defaults to `'smart'`.\n * Pass `'none'` to disable, or a string to append custom guidance.\n */\n readonly promptHint?: JsonPromptHint;\n}\n\n/**\n * Successful result of {@link AiAssist.generateJsonCompletion}.\n * @public\n */\nexport interface IGenerateJsonCompletionResult<T> {\n /** The validated JSON value. */\n readonly value: T;\n /** The raw response text returned by the provider. */\n readonly raw: string;\n /** The full underlying completion response. */\n readonly response: IAiCompletionResponse;\n}\n\nfunction applyPromptHint(prompt: AiPrompt, hint: JsonPromptHint): AiPrompt {\n if (hint === 'none') {\n return prompt;\n }\n const suffix = hint === 'smart' ? SMART_JSON_PROMPT_HINT : hint;\n const system = prompt.system.length > 0 ? `${prompt.system}\\n\\n${suffix}` : suffix;\n return new AiPrompt(prompt.user, system, prompt.attachments);\n}\n\n/**\n * Calls {@link AiAssist.callProviderCompletion}, then runs the response text\n * through a tolerant JSON converter (default:\n * {@link AiAssist.fencedStringifiedJson}) and the caller's\n * `converter`/`validator`. Returns the validated value plus the raw text and\n * underlying completion response for diagnostics.\n *\n * @remarks\n * The default smart prompt hint asks the model to emit raw JSON. The read-side\n * extractor still tolerates fences and prose, so models that ignore the hint\n * are still handled.\n *\n * Either `converter` or `jsonConverter` must be provided; passing both lets\n * `jsonConverter` win.\n *\n * @param params - Provider parameters plus JSON validation options.\n * @returns The validated value, the raw text, and the underlying response.\n * @public\n */\nexport async function generateJsonCompletion<T>(\n params: IGenerateJsonCompletionParams<T>\n): Promise<Result<IGenerateJsonCompletionResult<T>>> {\n const { converter, jsonConverter, promptHint = 'smart', prompt, ...rest } = params;\n\n if (jsonConverter === undefined && converter === undefined) {\n return fail('generateJsonCompletion: either converter or jsonConverter must be provided.');\n }\n\n const pipeline: Converter<T> = jsonConverter ?? fencedStringifiedJson<T>({ inner: converter! });\n const augmentedPrompt = applyPromptHint(prompt, promptHint);\n\n const response = await callProviderCompletion({ ...rest, prompt: augmentedPrompt });\n if (response.isFailure()) {\n return fail(response.message);\n }\n const completion = response.value;\n\n return pipeline\n .convert(completion.content)\n .withErrorFormat((msg) => `generateJsonCompletion: ${msg}`)\n .onSuccess((value) => succeed({ value, raw: completion.content, response: completion }));\n}\n"]}