@kortexya/reasoninglayer 0.2.1 → 0.2.2

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/README.md CHANGED
@@ -7,8 +7,8 @@ TypeScript SDK for the [Reasoning Layer](https://kortexya.com) API — a knowled
7
7
  - **Zero runtime dependencies** — only `fetch` and `AbortController` (ES2022)
8
8
  - **Dual ESM/CJS** — works in Node 18+, modern browsers, Deno, and Bun
9
9
  - **Full type safety** — strict TypeScript with discriminated unions, no `any` types
10
- - **28 resource clients** covering sorts, terms, inference, query, fuzzy logic, cognitive agents, causal reasoning, and more
11
- - **7 builder namespaces** — `Value`, `FeatureInput`, `TermInput`, `guard`, `SortBuilder`, `psi`, `allen`
10
+ - **29 resource clients** covering sorts, terms, inference, query, fuzzy logic, cognitive agents, causal reasoning, optimization, and more
11
+ - **8 builder namespaces** — `Value`, `FeatureInput`, `TermInput`, `guard`, `SortBuilder`, `psi`, `allen`, `LP`
12
12
  - **Automatic retry** — exponential backoff with jitter on 429 and 503 responses
13
13
  - **WebSocket** — real-time cognitive agent event subscriptions with auto-reconnect
14
14
  - **Error hierarchy** — typed errors for constraint violations, rate limits, timeouts, and network failures
@@ -107,6 +107,7 @@ console.log(result.solutions); // Solutions with bindings
107
107
  | `actionReviews` | Action reviews | approve, reject, modify autonomous actions |
108
108
  | `discovery` | Discovery | causal effect discovery, prediction |
109
109
  | `extract` | Extraction | entity extraction from text |
110
+ | `optimize` | Optimization | LP solve, KB-driven optimization |
110
111
 
111
112
  ## Configuration
112
113
 
@@ -167,7 +168,7 @@ try {
167
168
  The SDK provides builder functions for constructing API request values with full type safety:
168
169
 
169
170
  ```typescript
170
- import { Value, FeatureInput, TermInput, guard, allen, SortBuilder, psi } from '@kortexya/reasoninglayer';
171
+ import { Value, FeatureInput, TermInput, guard, allen, SortBuilder, psi, LP } from '@kortexya/reasoninglayer';
171
172
 
172
173
  // Tagged values (term CRUD)
173
174
  Value.string('hello') // { type: 'String', value: 'hello' }
@@ -185,6 +186,11 @@ guard('gt', 100) // { guard: { op: 'gt', value: 100 } }
185
186
  // Allen temporal relations
186
187
  allen('before') // { allen: 'before' }
187
188
 
189
+ // LP optimization
190
+ LP.maximize({ x: 3, y: 5 }) // objective function
191
+ LP.constraint({ x: 1, y: 3 }, '<=', 12) // linear constraint
192
+ LP.nonNegative('x', 'y') // variable bounds
193
+
188
194
  // Fluent sort builder
189
195
  new SortBuilder('employee')
190
196
  .parents(['person'])
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/config.ts
4
- var SDK_VERSION = "0.2.1";
4
+ var SDK_VERSION = "0.2.2";
5
5
  function resolveConfig(config) {
6
6
  if (!config.baseUrl) {
7
7
  throw new Error("ClientConfig.baseUrl is required");
@@ -12548,6 +12548,553 @@ var RagClient = class {
12548
12548
  }
12549
12549
  };
12550
12550
 
12551
+ // src/builders/lp.ts
12552
+ var LP = {
12553
+ /**
12554
+ * Create a maximization objective.
12555
+ *
12556
+ * @param coefficients - Map of variable names to their objective coefficients.
12557
+ * @returns An objective function to maximize.
12558
+ *
12559
+ * @remarks Serialization format: SDK-internal (compiled to constraint sorts).
12560
+ *
12561
+ * @example
12562
+ * ```typescript
12563
+ * LP.maximize({ chairs: 3, tables: 5 })
12564
+ * // { direction: 'maximize', coefficients: { chairs: 3, tables: 5 } }
12565
+ * ```
12566
+ */
12567
+ maximize(coefficients) {
12568
+ return { direction: "maximize", coefficients };
12569
+ },
12570
+ /**
12571
+ * Create a minimization objective.
12572
+ *
12573
+ * @param coefficients - Map of variable names to their objective coefficients.
12574
+ * @returns An objective function to minimize.
12575
+ *
12576
+ * @remarks Serialization format: SDK-internal (compiled to constraint sorts).
12577
+ *
12578
+ * @example
12579
+ * ```typescript
12580
+ * LP.minimize({ cost_a: 2, cost_b: 5 })
12581
+ * // { direction: 'minimize', coefficients: { cost_a: 2, cost_b: 5 } }
12582
+ * ```
12583
+ */
12584
+ minimize(coefficients) {
12585
+ return { direction: "minimize", coefficients };
12586
+ },
12587
+ /**
12588
+ * Create a linear constraint.
12589
+ *
12590
+ * @param coefficients - Map of variable names to their constraint coefficients.
12591
+ * @param op - Comparison operator: '<=', '>=', or '='.
12592
+ * @param rhs - Right-hand side constant.
12593
+ * @param label - Optional human-readable label.
12594
+ * @returns A linear constraint.
12595
+ *
12596
+ * @remarks Serialization format: SDK-internal (compiled to constraint sorts).
12597
+ *
12598
+ * @example
12599
+ * ```typescript
12600
+ * LP.constraint({ chairs: 1, tables: 3 }, '<=', 12, 'wood')
12601
+ * // { coefficients: { chairs: 1, tables: 3 }, op: '<=', rhs: 12, label: 'wood' }
12602
+ * ```
12603
+ */
12604
+ constraint(coefficients, op, rhs, label) {
12605
+ return label !== void 0 ? { coefficients, op, rhs, label } : { coefficients, op, rhs };
12606
+ },
12607
+ /**
12608
+ * Create non-negativity bounds (>= 0) for the given variables.
12609
+ *
12610
+ * @param variables - Variable names to constrain to be non-negative.
12611
+ * @returns A bounds map with `{ min: 0 }` for each variable.
12612
+ *
12613
+ * @remarks Serialization format: SDK-internal (compiled to constraint sorts).
12614
+ *
12615
+ * @example
12616
+ * ```typescript
12617
+ * LP.nonNegative('chairs', 'tables')
12618
+ * // { chairs: { min: 0 }, tables: { min: 0 } }
12619
+ * ```
12620
+ */
12621
+ nonNegative(...variables) {
12622
+ const bounds = {};
12623
+ for (const v of variables) {
12624
+ bounds[v] = { min: 0 };
12625
+ }
12626
+ return bounds;
12627
+ },
12628
+ /**
12629
+ * Create bounds for a variable.
12630
+ *
12631
+ * @param min - Lower bound (omit for unbounded below).
12632
+ * @param max - Upper bound (omit for unbounded above).
12633
+ * @returns Variable bounds specification.
12634
+ *
12635
+ * @remarks Serialization format: SDK-internal (compiled to constraint sorts).
12636
+ *
12637
+ * @example
12638
+ * ```typescript
12639
+ * LP.bounds(0, 100)
12640
+ * // { min: 0, max: 100 }
12641
+ * ```
12642
+ */
12643
+ bounds(min, max) {
12644
+ const b = {};
12645
+ if (min !== void 0) b.min = min;
12646
+ if (max !== void 0) b.max = max;
12647
+ return b;
12648
+ }
12649
+ };
12650
+ function compileLP(problem, solutionSortName) {
12651
+ const counter = { value: 0 };
12652
+ const nextVar = () => `?_lp_${counter.value++}`;
12653
+ const variableNames = discoverVariables(problem);
12654
+ if (variableNames.length === 0) {
12655
+ throw new Error("LP problem has no variables. At least one variable must appear in the objective or constraints.");
12656
+ }
12657
+ const varRefs = {};
12658
+ for (const name of variableNames) {
12659
+ varRefs[name] = { name: `?${name}` };
12660
+ }
12661
+ const allAntecedents = [];
12662
+ if (problem.bounds) {
12663
+ for (const [varName, bounds] of Object.entries(problem.bounds)) {
12664
+ if (!(varName in varRefs)) continue;
12665
+ const ref = varRefs[varName];
12666
+ if (bounds.min !== void 0 && bounds.max !== void 0) {
12667
+ allAntecedents.push({
12668
+ sort_name: "real_between_constraint",
12669
+ features: {
12670
+ var: ref,
12671
+ lower: bounds.min,
12672
+ upper: bounds.max
12673
+ }
12674
+ });
12675
+ } else {
12676
+ if (bounds.min !== void 0) {
12677
+ allAntecedents.push({
12678
+ sort_name: "real_ge_constraint",
12679
+ features: {
12680
+ left: ref,
12681
+ right: bounds.min
12682
+ }
12683
+ });
12684
+ }
12685
+ if (bounds.max !== void 0) {
12686
+ allAntecedents.push({
12687
+ sort_name: "real_le_constraint",
12688
+ features: {
12689
+ left: ref,
12690
+ right: bounds.max
12691
+ }
12692
+ });
12693
+ }
12694
+ }
12695
+ }
12696
+ }
12697
+ for (const constraint of problem.constraints) {
12698
+ const compiled = compileLinearExpression(constraint.coefficients, varRefs, nextVar);
12699
+ allAntecedents.push(...compiled.antecedents);
12700
+ const sortName = constraintOpToSort(constraint.op);
12701
+ allAntecedents.push({
12702
+ sort_name: sortName,
12703
+ features: {
12704
+ left: compiled.resultRef,
12705
+ right: constraint.rhs
12706
+ }
12707
+ });
12708
+ }
12709
+ const objectiveCompiled = compileLinearExpression(
12710
+ problem.objective.coefficients,
12711
+ varRefs,
12712
+ nextVar
12713
+ );
12714
+ allAntecedents.push(...objectiveCompiled.antecedents);
12715
+ let objectiveRef = objectiveCompiled.resultRef;
12716
+ if (typeof objectiveRef === "number") {
12717
+ const objVar = { name: "?_lp_objective" };
12718
+ allAntecedents.push({
12719
+ sort_name: "real_eq_constraint",
12720
+ features: {
12721
+ left: objVar,
12722
+ right: objectiveRef
12723
+ }
12724
+ });
12725
+ objectiveRef = objVar;
12726
+ }
12727
+ const objectiveSortName = problem.objective.direction === "maximize" ? "maximize_objective" : "minimize_objective";
12728
+ allAntecedents.push({
12729
+ sort_name: objectiveSortName,
12730
+ features: {
12731
+ expression: objectiveRef,
12732
+ name: "objective"
12733
+ }
12734
+ });
12735
+ const variableRefList = variableNames.map(
12736
+ (name) => varRefs[name]
12737
+ );
12738
+ allAntecedents.push({
12739
+ sort_name: "real_labeling_constraint",
12740
+ features: {
12741
+ variables: variableRefList
12742
+ }
12743
+ });
12744
+ const solutionFeatures = {};
12745
+ for (const name of variableNames) {
12746
+ solutionFeatures[name] = varRefs[name];
12747
+ }
12748
+ solutionFeatures["_objective"] = objectiveRef;
12749
+ const solutionTerm = {
12750
+ sort_name: solutionSortName,
12751
+ features: solutionFeatures
12752
+ };
12753
+ return { solutionTerm, antecedents: allAntecedents };
12754
+ }
12755
+ function discoverVariables(problem) {
12756
+ const vars = /* @__PURE__ */ new Set();
12757
+ for (const name of Object.keys(problem.objective.coefficients)) {
12758
+ vars.add(name);
12759
+ }
12760
+ for (const constraint of problem.constraints) {
12761
+ for (const name of Object.keys(constraint.coefficients)) {
12762
+ vars.add(name);
12763
+ }
12764
+ }
12765
+ if (problem.bounds) {
12766
+ for (const name of Object.keys(problem.bounds)) {
12767
+ vars.add(name);
12768
+ }
12769
+ }
12770
+ return Array.from(vars).sort();
12771
+ }
12772
+ function compileLinearExpression(expression, varRefs, nextVar) {
12773
+ const antecedents = [];
12774
+ const termResults = [];
12775
+ for (const [varName, coefficient] of Object.entries(expression)) {
12776
+ if (coefficient === 0) continue;
12777
+ const varRef = varRefs[varName];
12778
+ if (!varRef) continue;
12779
+ if (coefficient === 1) {
12780
+ termResults.push(varRef);
12781
+ } else {
12782
+ const resultVar = { name: nextVar() };
12783
+ antecedents.push({
12784
+ sort_name: "real_times_constraint",
12785
+ features: {
12786
+ coefficient,
12787
+ variable: varRef,
12788
+ result: resultVar
12789
+ }
12790
+ });
12791
+ termResults.push(resultVar);
12792
+ }
12793
+ }
12794
+ if (termResults.length === 0) {
12795
+ return { antecedents, resultRef: 0 };
12796
+ }
12797
+ if (termResults.length === 1) {
12798
+ return { antecedents, resultRef: termResults[0] };
12799
+ }
12800
+ let current = termResults[0];
12801
+ for (let i = 1; i < termResults.length; i++) {
12802
+ const sumVar = { name: nextVar() };
12803
+ antecedents.push({
12804
+ sort_name: "real_plus_constraint",
12805
+ features: {
12806
+ left: current,
12807
+ right: termResults[i],
12808
+ result: sumVar
12809
+ }
12810
+ });
12811
+ current = sumVar;
12812
+ }
12813
+ return { antecedents, resultRef: current };
12814
+ }
12815
+ function constraintOpToSort(op) {
12816
+ switch (op) {
12817
+ case "<=":
12818
+ return "real_le_constraint";
12819
+ case ">=":
12820
+ return "real_ge_constraint";
12821
+ case "=":
12822
+ return "real_eq_constraint";
12823
+ }
12824
+ }
12825
+
12826
+ // src/resources/optimize.ts
12827
+ var OptimizeClient = class {
12828
+ /** @internal */
12829
+ inferenceApi;
12830
+ /** @internal */
12831
+ sortsApi;
12832
+ /** @internal */
12833
+ queryApi;
12834
+ /** @internal */
12835
+ termsApi;
12836
+ /** @internal */
12837
+ tenantId;
12838
+ /** @internal */
12839
+ constructor(inferenceApi, sortsApi, queryApi, termsApi, tenantId) {
12840
+ this.inferenceApi = inferenceApi;
12841
+ this.sortsApi = sortsApi;
12842
+ this.queryApi = queryApi;
12843
+ this.termsApi = termsApi;
12844
+ this.tenantId = tenantId;
12845
+ }
12846
+ /**
12847
+ * Solve a linear program.
12848
+ *
12849
+ * @param problem - The LP problem definition with objective, constraints, and bounds.
12850
+ * @param options - Optional solver configuration (timeout, cleanup, etc.).
12851
+ * @returns The optimization result with variable values and objective value.
12852
+ *
12853
+ * @throws {Error} If the problem has no variables.
12854
+ *
12855
+ * @remarks
12856
+ * Internally creates a temporary sort and inference rule, runs backward chaining
12857
+ * to trigger the CLP(Q) simplex solver, then cleans up temporary artifacts.
12858
+ *
12859
+ * The solver uses exact rational arithmetic (Rational64). Solutions are converted
12860
+ * to JavaScript numbers (f64 approximation) for the response.
12861
+ *
12862
+ * @example
12863
+ * ```typescript
12864
+ * import { LP } from '@kortexya/reasoninglayer';
12865
+ *
12866
+ * const result = await client.optimize.solve({
12867
+ * objective: LP.maximize({ x: 1, y: 2 }),
12868
+ * constraints: [
12869
+ * LP.constraint({ x: 1, y: 1 }, '<=', 10),
12870
+ * ],
12871
+ * bounds: LP.nonNegative('x', 'y'),
12872
+ * });
12873
+ *
12874
+ * if (result.status === 'optimal') {
12875
+ * console.log(result.variables); // { x: 0, y: 10 }
12876
+ * console.log(result.objectiveValue); // 20
12877
+ * }
12878
+ * ```
12879
+ */
12880
+ async solve(problem, options) {
12881
+ const cleanup = options?.cleanup !== false;
12882
+ const timeoutMs = options?.timeoutMs ?? 3e4;
12883
+ const maxDepth = options?.maxDepth ?? 50;
12884
+ const suffix = generateShortId();
12885
+ const solutionSortName = `_lp_solution_${suffix}`;
12886
+ const compiled = compileLP(problem, solutionSortName);
12887
+ let sortId;
12888
+ let ruleTermId;
12889
+ try {
12890
+ const sortResponse = await this.sortsApi.bulkCreateSorts({
12891
+ sorts: [{ name: solutionSortName, parents: ["thing"] }]
12892
+ });
12893
+ sortId = sortResponse.data.sort_ids[solutionSortName];
12894
+ const ruleResponse = await this.inferenceApi.addRule({
12895
+ term: compiled.solutionTerm,
12896
+ antecedents: compiled.antecedents,
12897
+ certainty: 1
12898
+ });
12899
+ ruleTermId = ruleResponse.data.term.term_id;
12900
+ const bcResponse = await this.inferenceApi.backwardChain({
12901
+ goal: { sort_name: solutionSortName },
12902
+ max_solutions: 1,
12903
+ max_depth: maxDepth,
12904
+ timeout_ms: timeoutMs
12905
+ });
12906
+ const queryTimeMs = bcResponse.data.query_time_ms;
12907
+ if (bcResponse.data.solutions.length === 0) {
12908
+ return { status: "infeasible", solveTimeMs: queryTimeMs };
12909
+ }
12910
+ const solution = bcResponse.data.solutions[0];
12911
+ const variables = {};
12912
+ let objectiveValue = 0;
12913
+ for (const binding of solution.substitution.bindings) {
12914
+ const varName = binding.variable_name;
12915
+ if (!varName) continue;
12916
+ const value = parseFloat(binding.bound_to_display);
12917
+ if (isNaN(value)) continue;
12918
+ if (varName === "?_lp_objective") {
12919
+ objectiveValue = value;
12920
+ } else if (varName.startsWith("?") && !varName.startsWith("?_lp_")) {
12921
+ variables[varName.slice(1)] = value;
12922
+ }
12923
+ }
12924
+ return {
12925
+ status: "optimal",
12926
+ variables,
12927
+ objectiveValue,
12928
+ solveTimeMs: queryTimeMs
12929
+ };
12930
+ } finally {
12931
+ if (cleanup) {
12932
+ await this.cleanupArtifacts(ruleTermId, sortId);
12933
+ }
12934
+ }
12935
+ }
12936
+ /**
12937
+ * Solve an LP problem with variables and coefficients discovered from the knowledge base.
12938
+ *
12939
+ * @param config - Configuration specifying which sorts/features to query and how to
12940
+ * map them to LP variables, objective, and constraints.
12941
+ * @param options - Optional solver configuration.
12942
+ * @returns The optimization result plus the auto-generated LP and discovered terms.
12943
+ *
12944
+ * @throws {Error} If the specified sort is not found.
12945
+ * @throws {Error} If no terms are found for the variable sort.
12946
+ * @throws {Error} If a required feature is missing or non-numeric on a term.
12947
+ *
12948
+ * @remarks
12949
+ * This method queries existing knowledge base data to build the LP automatically:
12950
+ * 1. Resolves the variable sort name to its sort ID
12951
+ * 2. Queries all terms of that sort
12952
+ * 3. Extracts feature values to compute objective coefficients and constraint coefficients
12953
+ * 4. Builds and solves the LP
12954
+ *
12955
+ * @example
12956
+ * ```typescript
12957
+ * // Given products in the KB with features: name, profit, wood_cost, labor_cost
12958
+ * const result = await client.optimize.fromKnowledgeBase({
12959
+ * variables: { sort: 'product', nameFeature: 'name' },
12960
+ * objective: { direction: 'maximize', coefficientFeature: 'profit' },
12961
+ * resourceConstraints: [
12962
+ * { costFeature: 'wood_cost', capacity: 12, label: 'wood' },
12963
+ * { costFeature: 'labor_cost', capacity: 8, label: 'labor' },
12964
+ * ],
12965
+ * nonNegative: true,
12966
+ * });
12967
+ *
12968
+ * if (result.result.status === 'optimal') {
12969
+ * console.log(result.result.variables); // { chair: 2.4, table: 3.2 }
12970
+ * }
12971
+ * console.log(result.generatedProblem); // The auto-generated LP for inspection
12972
+ * ```
12973
+ */
12974
+ async fromKnowledgeBase(config, options) {
12975
+ const sortId = await this.resolveSortName(config.variables.sort);
12976
+ const queryResponse = await this.queryApi.findBySort({
12977
+ sort_id: sortId
12978
+ });
12979
+ const terms = queryResponse.data.terms;
12980
+ if (terms.length === 0) {
12981
+ throw new Error(
12982
+ `No terms found for sort '${config.variables.sort}'. Create terms with features [${config.objective.coefficientFeature}, ${config.resourceConstraints.map((r) => r.costFeature).join(", ")}] first.`
12983
+ );
12984
+ }
12985
+ const variableNames = [];
12986
+ const objectiveCoeffs = {};
12987
+ const constraintCoeffsMap = {};
12988
+ for (const rc of config.resourceConstraints) {
12989
+ constraintCoeffsMap[rc.costFeature] = {};
12990
+ }
12991
+ for (const term of terms) {
12992
+ const name = extractStringValue(term.features, config.variables.nameFeature);
12993
+ if (!name) {
12994
+ throw new Error(
12995
+ `Term ${term.id} of sort '${config.variables.sort}' is missing the name feature '${config.variables.nameFeature}' or it is not a string.`
12996
+ );
12997
+ }
12998
+ variableNames.push(name);
12999
+ const objCoeff = extractNumericValue(term.features, config.objective.coefficientFeature);
13000
+ if (objCoeff === null) {
13001
+ throw new Error(
13002
+ `Term '${name}' (${term.id}) is missing numeric feature '${config.objective.coefficientFeature}' for the objective.`
13003
+ );
13004
+ }
13005
+ objectiveCoeffs[name] = objCoeff;
13006
+ for (const rc of config.resourceConstraints) {
13007
+ const costCoeff = extractNumericValue(term.features, rc.costFeature);
13008
+ if (costCoeff === null) {
13009
+ throw new Error(
13010
+ `Term '${name}' (${term.id}) is missing numeric feature '${rc.costFeature}' for the resource constraint.`
13011
+ );
13012
+ }
13013
+ constraintCoeffsMap[rc.costFeature][name] = costCoeff;
13014
+ }
13015
+ }
13016
+ const constraints = config.resourceConstraints.map((rc) => ({
13017
+ coefficients: constraintCoeffsMap[rc.costFeature],
13018
+ op: rc.op ?? "<=",
13019
+ rhs: rc.capacity,
13020
+ ...rc.label ? { label: rc.label } : {}
13021
+ }));
13022
+ if (config.additionalConstraints) {
13023
+ constraints.push(...config.additionalConstraints);
13024
+ }
13025
+ const generatedProblem = {
13026
+ objective: {
13027
+ direction: config.objective.direction,
13028
+ coefficients: objectiveCoeffs
13029
+ },
13030
+ constraints,
13031
+ bounds: config.nonNegative ? Object.fromEntries(variableNames.map((n) => [n, { min: 0 }])) : void 0
13032
+ };
13033
+ const result = await this.solve(generatedProblem, options);
13034
+ return {
13035
+ result,
13036
+ generatedProblem,
13037
+ discoveredTerms: terms
13038
+ };
13039
+ }
13040
+ /**
13041
+ * Resolve a sort name to its sort ID by listing the tenant's sorts.
13042
+ *
13043
+ * @internal
13044
+ */
13045
+ async resolveSortName(sortName) {
13046
+ const response = await this.sortsApi.listSorts(this.tenantId);
13047
+ const sorts = response.data.sorts;
13048
+ const match = sorts.find((s) => s.name === sortName);
13049
+ if (!match) {
13050
+ const available = sorts.slice(0, 10).map((s) => s.name).join(", ");
13051
+ throw new Error(
13052
+ `Sort '${sortName}' not found. Available sorts: ${available}${sorts.length > 10 ? "..." : ""}`
13053
+ );
13054
+ }
13055
+ return match.id;
13056
+ }
13057
+ /**
13058
+ * Clean up temporary sort and rule artifacts (best-effort).
13059
+ *
13060
+ * @internal
13061
+ */
13062
+ async cleanupArtifacts(ruleTermId, sortId) {
13063
+ const promises = [];
13064
+ if (ruleTermId) {
13065
+ promises.push(
13066
+ this.termsApi.deleteTerm(ruleTermId).catch(() => {
13067
+ })
13068
+ );
13069
+ }
13070
+ if (sortId) {
13071
+ promises.push(
13072
+ this.sortsApi.deleteSort(sortId).catch(() => {
13073
+ })
13074
+ );
13075
+ }
13076
+ await Promise.all(promises);
13077
+ }
13078
+ };
13079
+ function generateShortId() {
13080
+ const timestamp = Date.now().toString(36);
13081
+ const random = Math.random().toString(36).slice(2, 8);
13082
+ return `${timestamp}_${random}`;
13083
+ }
13084
+ function extractStringValue(features, featureName) {
13085
+ const value = features[featureName];
13086
+ if (!value) return null;
13087
+ if (value.type === "String") return value.value;
13088
+ return null;
13089
+ }
13090
+ function extractNumericValue(features, featureName) {
13091
+ const value = features[featureName];
13092
+ if (!value) return null;
13093
+ if (value.type === "Integer") return value.value;
13094
+ if (value.type === "Real") return value.value;
13095
+ return null;
13096
+ }
13097
+
12551
13098
  // src/client.ts
12552
13099
  var ReasoningLayerClient = class {
12553
13100
  /** Sort (type hierarchy) operations. */
@@ -12634,6 +13181,8 @@ var ReasoningLayerClient = class {
12634
13181
  generation;
12635
13182
  /** Ontology RAG operations (embedding search + feature unification). */
12636
13183
  rag;
13184
+ /** Linear program optimization (CLP(Q) simplex solver via backward chaining). */
13185
+ optimize;
12637
13186
  /**
12638
13187
  * Create a new ReasoningLayerClient.
12639
13188
  *
@@ -12736,6 +13285,7 @@ var ReasoningLayerClient = class {
12736
13285
  this.ontology = new OntologyClient(generatedOntology);
12737
13286
  this.generation = new GenerationClient(generatedGeneration);
12738
13287
  this.rag = new RagClient(generatedRag);
13288
+ this.optimize = new OptimizeClient(generatedInference, generatedSorts, generatedQuery, generatedTerms, resolved.tenantId);
12739
13289
  }
12740
13290
  };
12741
13291
 
@@ -13610,6 +14160,7 @@ exports.ConstraintViolationError = ConstraintViolationError;
13610
14160
  exports.FeatureInput = FeatureInput;
13611
14161
  exports.FuzzyShape = FuzzyShape;
13612
14162
  exports.InternalServerError = InternalServerError;
14163
+ exports.LP = LP;
13613
14164
  exports.NetworkError = NetworkError;
13614
14165
  exports.NotFoundError = NotFoundError;
13615
14166
  exports.RateLimitError = RateLimitError;