@kortexya/reasoninglayer 0.2.1 → 0.2.3

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