@modelprofile.com/flexharness 10.14.0 → 10.15.0

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/ts/interfaces.ts CHANGED
@@ -687,6 +687,9 @@ export const FLEX_TOOL_CATALOG_LIMITS = Object.freeze({
687
687
  maxDeclarationBytes: 16 * 1024,
688
688
  maxTags: 16,
689
689
  maxTagCharacters: 48,
690
+ maxAliases: 16,
691
+ maxAliasCharacters: 64,
692
+ maxVocabularyWords: 1024,
690
693
  maxExamples: 4,
691
694
  maxExampleBytes: 1024,
692
695
  maxSchemaBytes: 64 * 1024,
@@ -697,8 +700,16 @@ export const FLEX_TOOL_CATALOG_LIMITS = Object.freeze({
697
700
  maxDescribeTypes: 32,
698
701
  maxDescribeBytes: 64 * 1024,
699
702
  maxParamIssues: 10,
703
+ maxOutputTypeDepth: 32,
700
704
  });
701
705
 
706
+ /**
707
+ * How many levels of named types a TypeScript declaration declares for a method's result by
708
+ * default: none. The result names its types, and `describe_tools({ types })` declares them on
709
+ * request, as a model needs them only to read fields of a result it has not seen.
710
+ */
711
+ export const FLEX_TOOL_CATALOG_DEFAULT_OUTPUT_TYPE_DEPTH = 0;
712
+
702
713
  export interface IFlexCatalogSearchInput {
703
714
  /** Words to rank methods by. */
704
715
  query?: string;
@@ -788,10 +799,16 @@ export interface IFlexCatalogMethod<TScope = unknown, TParams = any, TResult = u
788
799
  method: string;
789
800
  /** One line of at most 120 characters, shown in search results. */
790
801
  summary: string;
791
- /** The full description, shown with the declaration. */
802
+ /** The full description, shown with the declaration. An empty or blank one counts as absent. */
792
803
  description?: string;
793
804
  /** More words `search_tools` matches. */
794
805
  tags?: readonly string[];
806
+ /**
807
+ * Other names of the method, such as the one its users' language or a former API gives it:
808
+ * `search_tools` weighs them like the method's name, and ranks the method first for a query that
809
+ * names one.
810
+ */
811
+ aliases?: readonly string[];
795
812
  /** Code shown as `@example` in the declaration. */
796
813
  examples?: readonly string[];
797
814
  /** The parameter object's schema; `execute` validates every call against it. */
@@ -838,18 +855,34 @@ export interface IFlexCatalogProposalContext<TScope = unknown> {
838
855
 
839
856
  /** A named type that method declarations refer to; it needs a `declaration`, a `schema`, or both. */
840
857
  export interface IFlexCatalogType {
841
- /** A JavaScript identifier such as `IMoney`. */
858
+ /**
859
+ * The type's name, such as `IMoney`, which `$ref`s to `#/$defs/<name>` use. A name that is no
860
+ * JavaScript identifier, such as `IEvent_order.created` as schema generators name instances of
861
+ * generics, is declared under an identifier made of it: each other character becomes `_`, and a
862
+ * reserved word or a leading digit is escaped with `_` (`IEvent_order_created`). Its declaration
863
+ * names the original, and `describe_tools` takes either.
864
+ */
842
865
  name: string;
866
+ /** An empty or blank description counts as absent. */
843
867
  description?: string;
844
868
  /** Validates parameters that refer to this type, and generates its declaration. */
845
869
  schema?: TFlexCatalogSchema;
846
- /** Declaration text that replaces the generated one, such as `interface IMoney { … }`. */
870
+ /**
871
+ * Declaration text that replaces the generated one, such as `interface IMoney { … }`. It declares
872
+ * the identifier the type is declared under.
873
+ */
847
874
  declaration?: string;
848
875
  }
849
876
 
850
877
  export interface IFlexToolCatalog<TScope = unknown> {
851
878
  methods: readonly IFlexCatalogMethod<TScope>[];
852
879
  types?: readonly IFlexCatalogType[];
880
+ /**
881
+ * The words the catalog's users say for its own words, by the catalog's word:
882
+ * `{ voucher: ['Beleg', 'Belege'], 'gross amount': ['Bruttobetrag'] }`. A `search_tools` query that
883
+ * says every word of an alias searches for the catalog's words as well.
884
+ */
885
+ vocabulary?: Readonly<Record<string, readonly string[]>>;
853
886
  /**
854
887
  * Receives the calls `onCall` proposed, as one batch: the proposed call of an `execute`, or every
855
888
  * call a `run_code` program proposed, once the program finished. A failed program proposes
@@ -867,6 +900,20 @@ export interface IFlexToolCatalogOptions {
867
900
  * across the session, or `json-schema` with each method's self-contained JSON Schema.
868
901
  */
869
902
  declarations?: 'typescript' | 'json-schema';
903
+ /**
904
+ * How many levels of named types a TypeScript declaration declares for a method's result:
905
+ * `0` (the default) none, `1` the types the result names, each further level the types those
906
+ * name. A parameter's types are always declared in full, since a call has to match them. The
907
+ * declaration lists the types it names but does not declare; `describe_tools({ types })`
908
+ * declares them on request.
909
+ */
910
+ outputTypeDepth?: number;
911
+ /**
912
+ * `search_tools` follows its results with the declaration of the top match when one match
913
+ * clearly leads, so the model can call it without a `describe_tools` step: the only match, or one
914
+ * whose name or alias the query names that ranks 1.25 times higher than the next. Default `true`.
915
+ */
916
+ describeTopMatch?: boolean;
870
917
  /**
871
918
  * Adds `run_code`, which runs a short TypeScript or JavaScript program against the catalog in a
872
919
  * QuickJS sandbox. Needs the optional peers `quickjs-emscripten-core`,
@@ -3,6 +3,8 @@ import {
3
3
  FLEX_CODE_MODE_DEFAULT_LIMITS,
4
4
  FLEX_CODE_MODE_MAXIMUM_LIMITS,
5
5
  FLEX_REVERSION_DEFAULT_LIMITS,
6
+ FLEX_TOOL_CATALOG_DEFAULT_OUTPUT_TYPE_DEPTH,
7
+ FLEX_TOOL_CATALOG_LIMITS,
6
8
  FLEX_REVERSION_MAXIMUM_LIMITS,
7
9
  } from './interfaces.js';
8
10
  import type {
@@ -162,6 +164,8 @@ export function normalizeSubagents(
162
164
 
163
165
  export interface INormalizedToolCatalogOptions {
164
166
  readonly declarations: 'typescript' | 'json-schema';
167
+ readonly outputTypeDepth: number;
168
+ readonly describeTopMatch: boolean;
165
169
  /** The limits of `run_code`; absent while code mode is off. */
166
170
  readonly codeMode?: Readonly<IFlexCodeModeLimits>;
167
171
  }
@@ -175,16 +179,35 @@ const isPlainOptions = (value: unknown): value is Record<string, unknown> =>
175
179
  export function normalizeToolCatalogOptions(
176
180
  options: IFlexToolCatalogOptions | undefined,
177
181
  ): INormalizedToolCatalogOptions {
178
- if (options === undefined) return Object.freeze({ declarations: 'typescript' });
182
+ if (options === undefined) {
183
+ return Object.freeze({
184
+ declarations: 'typescript',
185
+ outputTypeDepth: FLEX_TOOL_CATALOG_DEFAULT_OUTPUT_TYPE_DEPTH,
186
+ describeTopMatch: true,
187
+ });
188
+ }
179
189
  if (!isPlainOptions(options)) throw new FlexHarnessValidationError('toolCatalog must be a plain object.');
180
- const unsupported = Object.keys(options).find((key) => key !== 'declarations' && key !== 'codeMode');
190
+ const unsupported = Object.keys(options).find(
191
+ (key) => !['declarations', 'outputTypeDepth', 'describeTopMatch', 'codeMode'].includes(key),
192
+ );
181
193
  if (unsupported) throw new FlexHarnessValidationError(`toolCatalog does not support "${unsupported}".`);
182
194
  const declarations = options.declarations ?? 'typescript';
183
195
  if (declarations !== 'typescript' && declarations !== 'json-schema') {
184
196
  throw new FlexHarnessValidationError('toolCatalog.declarations must be "typescript" or "json-schema".');
185
197
  }
198
+ const outputTypeDepth: unknown = options.outputTypeDepth ?? FLEX_TOOL_CATALOG_DEFAULT_OUTPUT_TYPE_DEPTH;
199
+ if (
200
+ typeof outputTypeDepth !== 'number' || !Number.isSafeInteger(outputTypeDepth)
201
+ || outputTypeDepth < 0 || outputTypeDepth > FLEX_TOOL_CATALOG_LIMITS.maxOutputTypeDepth
202
+ ) {
203
+ throw new FlexHarnessValidationError(
204
+ `toolCatalog.outputTypeDepth must be an integer from 0 through ${FLEX_TOOL_CATALOG_LIMITS.maxOutputTypeDepth}.`,
205
+ );
206
+ }
207
+ const describeTopMatch = options.describeTopMatch ?? true;
208
+ if (typeof describeTopMatch !== 'boolean') throw new FlexHarnessValidationError('toolCatalog.describeTopMatch must be a boolean.');
186
209
  const codeMode = normalizeCodeModeLimits(options.codeMode);
187
- return Object.freeze({ declarations, ...(codeMode ? { codeMode } : {}) });
210
+ return Object.freeze({ declarations, outputTypeDepth, describeTopMatch, ...(codeMode ? { codeMode } : {}) });
188
211
  }
189
212
 
190
213
  function normalizeCodeModeLimits(codeMode: unknown): Readonly<IFlexCodeModeLimits> | undefined {