@agentforge/core 0.15.5 → 0.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +64 -28
- package/dist/index.d.cts +34 -24
- package/dist/index.d.ts +34 -24
- package/dist/index.js +64 -28
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -794,21 +794,42 @@ function toolBuilder() {
|
|
|
794
794
|
// src/langchain/converter.ts
|
|
795
795
|
var import_tools = require("@langchain/core/tools");
|
|
796
796
|
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
797
|
+
function serializeToolResult(result) {
|
|
798
|
+
if (typeof result === "string") {
|
|
799
|
+
return result;
|
|
800
|
+
}
|
|
801
|
+
if (typeof result === "object" && result !== null) {
|
|
802
|
+
return JSON.stringify(result, null, 2);
|
|
803
|
+
}
|
|
804
|
+
return String(result);
|
|
805
|
+
}
|
|
806
|
+
function isJsonSchemaObject(value) {
|
|
807
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
808
|
+
}
|
|
809
|
+
function isJsonSchemaDefinitionMap(value) {
|
|
810
|
+
if (!isJsonSchemaObject(value)) {
|
|
811
|
+
return false;
|
|
812
|
+
}
|
|
813
|
+
return Object.values(value).every(isJsonSchemaObject);
|
|
814
|
+
}
|
|
815
|
+
function extractToolSchema(jsonSchema) {
|
|
816
|
+
if (!isJsonSchemaObject(jsonSchema)) {
|
|
817
|
+
return {};
|
|
818
|
+
}
|
|
819
|
+
const ref = jsonSchema.$ref;
|
|
820
|
+
const definitions = jsonSchema.definitions;
|
|
821
|
+
if (typeof ref !== "string" || !isJsonSchemaDefinitionMap(definitions)) {
|
|
822
|
+
return jsonSchema;
|
|
823
|
+
}
|
|
824
|
+
const refName = ref.replace("#/definitions/", "");
|
|
825
|
+
return definitions[refName] ?? jsonSchema;
|
|
826
|
+
}
|
|
797
827
|
function toLangChainTool(tool) {
|
|
798
828
|
return new import_tools.DynamicStructuredTool({
|
|
799
829
|
name: tool.metadata.name,
|
|
800
830
|
description: tool.metadata.description,
|
|
801
831
|
schema: tool.schema,
|
|
802
|
-
func: async (input) =>
|
|
803
|
-
const result = await tool.invoke(input);
|
|
804
|
-
if (typeof result === "string") {
|
|
805
|
-
return result;
|
|
806
|
-
}
|
|
807
|
-
if (typeof result === "object" && result !== null) {
|
|
808
|
-
return JSON.stringify(result, null, 2);
|
|
809
|
-
}
|
|
810
|
-
return String(result);
|
|
811
|
-
}
|
|
832
|
+
func: async (input) => serializeToolResult(await tool.invoke(input))
|
|
812
833
|
});
|
|
813
834
|
}
|
|
814
835
|
function toLangChainTools(tools) {
|
|
@@ -820,11 +841,7 @@ function getToolJsonSchema(tool) {
|
|
|
820
841
|
$refStrategy: "none"
|
|
821
842
|
// Don't use $ref for nested schemas
|
|
822
843
|
});
|
|
823
|
-
|
|
824
|
-
const refName = jsonSchema.$ref.replace("#/definitions/", "");
|
|
825
|
-
return jsonSchema.definitions[refName] || jsonSchema;
|
|
826
|
-
}
|
|
827
|
-
return jsonSchema;
|
|
844
|
+
return extractToolSchema(jsonSchema);
|
|
828
845
|
}
|
|
829
846
|
function getToolDescription(tool) {
|
|
830
847
|
const { metadata } = tool;
|
|
@@ -1566,7 +1583,7 @@ function createToolExecutor(config = {}) {
|
|
|
1566
1583
|
}
|
|
1567
1584
|
return Math.min(delay, maxDelay);
|
|
1568
1585
|
}
|
|
1569
|
-
function
|
|
1586
|
+
function toError2(error) {
|
|
1570
1587
|
if (error instanceof Error) {
|
|
1571
1588
|
return error;
|
|
1572
1589
|
}
|
|
@@ -1597,7 +1614,7 @@ function createToolExecutor(config = {}) {
|
|
|
1597
1614
|
try {
|
|
1598
1615
|
return await executeFn.call(tool, input);
|
|
1599
1616
|
} catch (error) {
|
|
1600
|
-
const currentError =
|
|
1617
|
+
const currentError = toError2(error);
|
|
1601
1618
|
lastError = currentError;
|
|
1602
1619
|
if (policy.retryableErrors && policy.retryableErrors.length > 0) {
|
|
1603
1620
|
const isRetryable = policy.retryableErrors.some(
|
|
@@ -1635,7 +1652,7 @@ function createToolExecutor(config = {}) {
|
|
|
1635
1652
|
return result;
|
|
1636
1653
|
} catch (error) {
|
|
1637
1654
|
const duration = Date.now() - startTime;
|
|
1638
|
-
const normalizedError =
|
|
1655
|
+
const normalizedError = toError2(error);
|
|
1639
1656
|
metrics.totalExecutions++;
|
|
1640
1657
|
metrics.failedExecutions++;
|
|
1641
1658
|
metrics.totalDuration += duration;
|
|
@@ -1902,6 +1919,15 @@ function createManagedTool(config) {
|
|
|
1902
1919
|
}
|
|
1903
1920
|
|
|
1904
1921
|
// src/tools/composition.ts
|
|
1922
|
+
function isConditionalStep(step) {
|
|
1923
|
+
return !Array.isArray(step) && "condition" in step;
|
|
1924
|
+
}
|
|
1925
|
+
function calculateRetryDelay(attempt, delay, backoff) {
|
|
1926
|
+
return backoff === "exponential" ? delay * Math.pow(2, attempt - 1) : delay * attempt;
|
|
1927
|
+
}
|
|
1928
|
+
function toError(error) {
|
|
1929
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
1930
|
+
}
|
|
1905
1931
|
function sequential(tools) {
|
|
1906
1932
|
return {
|
|
1907
1933
|
name: `sequential(${tools.map((t) => t.name).join(" -> ")})`,
|
|
@@ -1945,7 +1971,7 @@ function composeTool(config) {
|
|
|
1945
1971
|
for (const step of config.steps) {
|
|
1946
1972
|
if (Array.isArray(step)) {
|
|
1947
1973
|
result = await parallel(step).invoke(result);
|
|
1948
|
-
} else if (
|
|
1974
|
+
} else if (isConditionalStep(step)) {
|
|
1949
1975
|
result = await conditional(step).invoke(result);
|
|
1950
1976
|
} else {
|
|
1951
1977
|
result = await step.invoke(result);
|
|
@@ -1960,18 +1986,21 @@ function composeTool(config) {
|
|
|
1960
1986
|
}
|
|
1961
1987
|
function retry(tool, options = {}) {
|
|
1962
1988
|
const { maxAttempts = 3, delay = 1e3, backoff = "exponential" } = options;
|
|
1989
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
1990
|
+
throw new Error("Invalid retry options: maxAttempts must be an integer >= 1");
|
|
1991
|
+
}
|
|
1963
1992
|
return {
|
|
1964
1993
|
name: `retry(${tool.name})`,
|
|
1965
1994
|
description: `${tool.description} (with retry)`,
|
|
1966
1995
|
invoke: async (input) => {
|
|
1967
|
-
let lastError;
|
|
1996
|
+
let lastError = new Error(`Tool ${tool.name} failed without an explicit error`);
|
|
1968
1997
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1969
1998
|
try {
|
|
1970
1999
|
return await tool.invoke(input);
|
|
1971
2000
|
} catch (error) {
|
|
1972
|
-
lastError = error;
|
|
2001
|
+
lastError = toError(error);
|
|
1973
2002
|
if (attempt < maxAttempts) {
|
|
1974
|
-
const waitTime =
|
|
2003
|
+
const waitTime = calculateRetryDelay(attempt, delay, backoff);
|
|
1975
2004
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
1976
2005
|
}
|
|
1977
2006
|
}
|
|
@@ -1985,12 +2014,19 @@ function timeout(tool, ms) {
|
|
|
1985
2014
|
name: `timeout(${tool.name})`,
|
|
1986
2015
|
description: `${tool.description} (with ${ms}ms timeout)`,
|
|
1987
2016
|
invoke: async (input) => {
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
)
|
|
1993
|
-
|
|
2017
|
+
let timer;
|
|
2018
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
2019
|
+
timer = setTimeout(() => {
|
|
2020
|
+
reject(new Error(`Tool ${tool.name} timed out after ${ms}ms`));
|
|
2021
|
+
}, ms);
|
|
2022
|
+
});
|
|
2023
|
+
try {
|
|
2024
|
+
return await Promise.race([tool.invoke(input), timeoutPromise]);
|
|
2025
|
+
} finally {
|
|
2026
|
+
if (timer !== void 0) {
|
|
2027
|
+
clearTimeout(timer);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
1994
2030
|
}
|
|
1995
2031
|
};
|
|
1996
2032
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1670,54 +1670,57 @@ declare function createManagedTool<TContext = any, TInput = any, TOutput = any>(
|
|
|
1670
1670
|
* Tool Composition - Compose tools into higher-level operations
|
|
1671
1671
|
* @module tools/composition
|
|
1672
1672
|
*/
|
|
1673
|
-
|
|
1673
|
+
type RetryBackoffStrategy = 'linear' | 'exponential';
|
|
1674
|
+
interface RetryOptions$1 {
|
|
1675
|
+
maxAttempts?: number;
|
|
1676
|
+
delay?: number;
|
|
1677
|
+
backoff?: RetryBackoffStrategy;
|
|
1678
|
+
}
|
|
1679
|
+
interface ComposedTool<TInput = unknown, TOutput = unknown> {
|
|
1674
1680
|
name: string;
|
|
1675
1681
|
description: string;
|
|
1676
|
-
invoke
|
|
1682
|
+
invoke(input: TInput): Promise<TOutput>;
|
|
1677
1683
|
}
|
|
1678
|
-
interface ConditionalConfig {
|
|
1679
|
-
condition
|
|
1680
|
-
onTrue: ComposedTool
|
|
1681
|
-
onFalse: ComposedTool
|
|
1684
|
+
interface ConditionalConfig<TInput = unknown, TTrueOutput = unknown, TFalseOutput = unknown> {
|
|
1685
|
+
condition(input: TInput): boolean | Promise<boolean>;
|
|
1686
|
+
onTrue: ComposedTool<TInput, TTrueOutput>;
|
|
1687
|
+
onFalse: ComposedTool<TInput, TFalseOutput>;
|
|
1682
1688
|
}
|
|
1683
|
-
|
|
1689
|
+
type ComposedStep = ComposedTool<unknown, unknown> | ComposedTool<unknown, unknown>[] | ConditionalConfig<unknown, unknown, unknown>;
|
|
1690
|
+
interface ComposeToolConfig<TOutput = unknown> {
|
|
1684
1691
|
name: string;
|
|
1685
1692
|
description?: string;
|
|
1686
|
-
steps:
|
|
1687
|
-
transformResult?: (result:
|
|
1693
|
+
steps: ComposedStep[];
|
|
1694
|
+
transformResult?: (result: unknown) => TOutput;
|
|
1688
1695
|
}
|
|
1689
1696
|
/**
|
|
1690
1697
|
* Execute tools sequentially
|
|
1691
1698
|
*/
|
|
1692
|
-
declare function sequential(tools: ComposedTool[]): ComposedTool
|
|
1699
|
+
declare function sequential<TInput = unknown>(tools: ComposedTool<unknown, unknown>[]): ComposedTool<TInput, unknown>;
|
|
1693
1700
|
/**
|
|
1694
1701
|
* Execute tools in parallel
|
|
1695
1702
|
*/
|
|
1696
|
-
declare function parallel(tools: ComposedTool[]): ComposedTool
|
|
1703
|
+
declare function parallel<TInput = unknown>(tools: ComposedTool<TInput, unknown>[]): ComposedTool<TInput, unknown[]>;
|
|
1697
1704
|
/**
|
|
1698
1705
|
* Execute tool conditionally
|
|
1699
1706
|
*/
|
|
1700
|
-
declare function conditional(config: ConditionalConfig): ComposedTool
|
|
1707
|
+
declare function conditional<TInput = unknown, TTrueOutput = unknown, TFalseOutput = unknown>(config: ConditionalConfig<TInput, TTrueOutput, TFalseOutput>): ComposedTool<TInput, TTrueOutput | TFalseOutput>;
|
|
1701
1708
|
/**
|
|
1702
1709
|
* Compose tools into a complex workflow
|
|
1703
1710
|
*/
|
|
1704
|
-
declare function composeTool(config: ComposeToolConfig): ComposedTool
|
|
1711
|
+
declare function composeTool<TInput = unknown, TOutput = unknown>(config: ComposeToolConfig<TOutput>): ComposedTool<TInput, TOutput>;
|
|
1705
1712
|
/**
|
|
1706
1713
|
* Create a tool that retries on failure
|
|
1707
1714
|
*/
|
|
1708
|
-
declare function retry(tool: ComposedTool, options?:
|
|
1709
|
-
maxAttempts?: number;
|
|
1710
|
-
delay?: number;
|
|
1711
|
-
backoff?: 'linear' | 'exponential';
|
|
1712
|
-
}): ComposedTool;
|
|
1715
|
+
declare function retry<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, options?: RetryOptions$1): ComposedTool<TInput, TOutput>;
|
|
1713
1716
|
/**
|
|
1714
1717
|
* Create a tool that times out
|
|
1715
1718
|
*/
|
|
1716
|
-
declare function timeout(tool: ComposedTool, ms: number): ComposedTool
|
|
1719
|
+
declare function timeout<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, ms: number): ComposedTool<TInput, TOutput>;
|
|
1717
1720
|
/**
|
|
1718
1721
|
* Create a tool that caches results
|
|
1719
1722
|
*/
|
|
1720
|
-
declare function cache(tool: ComposedTool, ttl?: number): ComposedTool
|
|
1723
|
+
declare function cache<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, ttl?: number): ComposedTool<TInput, TOutput>;
|
|
1721
1724
|
|
|
1722
1725
|
/**
|
|
1723
1726
|
* Tool Mocking & Testing - Mock tools for testing
|
|
@@ -1791,6 +1794,13 @@ declare function createToolSimulator(config: ToolSimulatorConfig): {
|
|
|
1791
1794
|
* ```
|
|
1792
1795
|
*/
|
|
1793
1796
|
|
|
1797
|
+
type RuntimeSchema<TInput = unknown> = z.ZodSchema<TInput>;
|
|
1798
|
+
type JsonSchemaObject = Record<string, unknown>;
|
|
1799
|
+
interface LangChainConvertibleTool<TInput = unknown, TOutput = unknown> {
|
|
1800
|
+
metadata: ToolMetadata;
|
|
1801
|
+
schema: RuntimeSchema<TInput>;
|
|
1802
|
+
invoke(input: TInput): Promise<TOutput>;
|
|
1803
|
+
}
|
|
1794
1804
|
/**
|
|
1795
1805
|
* Convert an AgentForge tool to a LangChain DynamicStructuredTool
|
|
1796
1806
|
*
|
|
@@ -1823,7 +1833,7 @@ declare function createToolSimulator(config: ToolSimulatorConfig): {
|
|
|
1823
1833
|
* });
|
|
1824
1834
|
* ```
|
|
1825
1835
|
*/
|
|
1826
|
-
declare function toLangChainTool(tool: Tool<
|
|
1836
|
+
declare function toLangChainTool<TInput, TOutput>(tool: Tool<TInput, TOutput>): DynamicStructuredTool<RuntimeSchema<TInput>, TInput, TInput, string>;
|
|
1827
1837
|
/**
|
|
1828
1838
|
* Convert multiple AgentForge tools to LangChain tools
|
|
1829
1839
|
*
|
|
@@ -1841,7 +1851,7 @@ declare function toLangChainTool(tool: Tool<any, any>): DynamicStructuredTool<an
|
|
|
1841
1851
|
* });
|
|
1842
1852
|
* ```
|
|
1843
1853
|
*/
|
|
1844
|
-
declare function toLangChainTools(tools:
|
|
1854
|
+
declare function toLangChainTools(tools: readonly LangChainConvertibleTool[]): DynamicStructuredTool[];
|
|
1845
1855
|
/**
|
|
1846
1856
|
* Get the JSON Schema representation of a tool's input schema
|
|
1847
1857
|
*
|
|
@@ -1856,7 +1866,7 @@ declare function toLangChainTools(tools: Tool<any, any>[]): DynamicStructuredToo
|
|
|
1856
1866
|
* console.log(JSON.stringify(schema, null, 2));
|
|
1857
1867
|
* ```
|
|
1858
1868
|
*/
|
|
1859
|
-
declare function getToolJsonSchema(tool: Tool<
|
|
1869
|
+
declare function getToolJsonSchema<TInput, TOutput>(tool: Tool<TInput, TOutput>): JsonSchemaObject;
|
|
1860
1870
|
/**
|
|
1861
1871
|
* Get tool metadata in a format suitable for LLM prompts
|
|
1862
1872
|
*
|
|
@@ -1877,7 +1887,7 @@ declare function getToolJsonSchema(tool: Tool<any, any>): Record<string, any>;
|
|
|
1877
1887
|
* // ...
|
|
1878
1888
|
* ```
|
|
1879
1889
|
*/
|
|
1880
|
-
declare function getToolDescription(tool: Tool<
|
|
1890
|
+
declare function getToolDescription<TInput, TOutput>(tool: Tool<TInput, TOutput>): string;
|
|
1881
1891
|
|
|
1882
1892
|
/**
|
|
1883
1893
|
* LangGraph State Utilities
|
package/dist/index.d.ts
CHANGED
|
@@ -1670,54 +1670,57 @@ declare function createManagedTool<TContext = any, TInput = any, TOutput = any>(
|
|
|
1670
1670
|
* Tool Composition - Compose tools into higher-level operations
|
|
1671
1671
|
* @module tools/composition
|
|
1672
1672
|
*/
|
|
1673
|
-
|
|
1673
|
+
type RetryBackoffStrategy = 'linear' | 'exponential';
|
|
1674
|
+
interface RetryOptions$1 {
|
|
1675
|
+
maxAttempts?: number;
|
|
1676
|
+
delay?: number;
|
|
1677
|
+
backoff?: RetryBackoffStrategy;
|
|
1678
|
+
}
|
|
1679
|
+
interface ComposedTool<TInput = unknown, TOutput = unknown> {
|
|
1674
1680
|
name: string;
|
|
1675
1681
|
description: string;
|
|
1676
|
-
invoke
|
|
1682
|
+
invoke(input: TInput): Promise<TOutput>;
|
|
1677
1683
|
}
|
|
1678
|
-
interface ConditionalConfig {
|
|
1679
|
-
condition
|
|
1680
|
-
onTrue: ComposedTool
|
|
1681
|
-
onFalse: ComposedTool
|
|
1684
|
+
interface ConditionalConfig<TInput = unknown, TTrueOutput = unknown, TFalseOutput = unknown> {
|
|
1685
|
+
condition(input: TInput): boolean | Promise<boolean>;
|
|
1686
|
+
onTrue: ComposedTool<TInput, TTrueOutput>;
|
|
1687
|
+
onFalse: ComposedTool<TInput, TFalseOutput>;
|
|
1682
1688
|
}
|
|
1683
|
-
|
|
1689
|
+
type ComposedStep = ComposedTool<unknown, unknown> | ComposedTool<unknown, unknown>[] | ConditionalConfig<unknown, unknown, unknown>;
|
|
1690
|
+
interface ComposeToolConfig<TOutput = unknown> {
|
|
1684
1691
|
name: string;
|
|
1685
1692
|
description?: string;
|
|
1686
|
-
steps:
|
|
1687
|
-
transformResult?: (result:
|
|
1693
|
+
steps: ComposedStep[];
|
|
1694
|
+
transformResult?: (result: unknown) => TOutput;
|
|
1688
1695
|
}
|
|
1689
1696
|
/**
|
|
1690
1697
|
* Execute tools sequentially
|
|
1691
1698
|
*/
|
|
1692
|
-
declare function sequential(tools: ComposedTool[]): ComposedTool
|
|
1699
|
+
declare function sequential<TInput = unknown>(tools: ComposedTool<unknown, unknown>[]): ComposedTool<TInput, unknown>;
|
|
1693
1700
|
/**
|
|
1694
1701
|
* Execute tools in parallel
|
|
1695
1702
|
*/
|
|
1696
|
-
declare function parallel(tools: ComposedTool[]): ComposedTool
|
|
1703
|
+
declare function parallel<TInput = unknown>(tools: ComposedTool<TInput, unknown>[]): ComposedTool<TInput, unknown[]>;
|
|
1697
1704
|
/**
|
|
1698
1705
|
* Execute tool conditionally
|
|
1699
1706
|
*/
|
|
1700
|
-
declare function conditional(config: ConditionalConfig): ComposedTool
|
|
1707
|
+
declare function conditional<TInput = unknown, TTrueOutput = unknown, TFalseOutput = unknown>(config: ConditionalConfig<TInput, TTrueOutput, TFalseOutput>): ComposedTool<TInput, TTrueOutput | TFalseOutput>;
|
|
1701
1708
|
/**
|
|
1702
1709
|
* Compose tools into a complex workflow
|
|
1703
1710
|
*/
|
|
1704
|
-
declare function composeTool(config: ComposeToolConfig): ComposedTool
|
|
1711
|
+
declare function composeTool<TInput = unknown, TOutput = unknown>(config: ComposeToolConfig<TOutput>): ComposedTool<TInput, TOutput>;
|
|
1705
1712
|
/**
|
|
1706
1713
|
* Create a tool that retries on failure
|
|
1707
1714
|
*/
|
|
1708
|
-
declare function retry(tool: ComposedTool, options?:
|
|
1709
|
-
maxAttempts?: number;
|
|
1710
|
-
delay?: number;
|
|
1711
|
-
backoff?: 'linear' | 'exponential';
|
|
1712
|
-
}): ComposedTool;
|
|
1715
|
+
declare function retry<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, options?: RetryOptions$1): ComposedTool<TInput, TOutput>;
|
|
1713
1716
|
/**
|
|
1714
1717
|
* Create a tool that times out
|
|
1715
1718
|
*/
|
|
1716
|
-
declare function timeout(tool: ComposedTool, ms: number): ComposedTool
|
|
1719
|
+
declare function timeout<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, ms: number): ComposedTool<TInput, TOutput>;
|
|
1717
1720
|
/**
|
|
1718
1721
|
* Create a tool that caches results
|
|
1719
1722
|
*/
|
|
1720
|
-
declare function cache(tool: ComposedTool, ttl?: number): ComposedTool
|
|
1723
|
+
declare function cache<TInput = unknown, TOutput = unknown>(tool: ComposedTool<TInput, TOutput>, ttl?: number): ComposedTool<TInput, TOutput>;
|
|
1721
1724
|
|
|
1722
1725
|
/**
|
|
1723
1726
|
* Tool Mocking & Testing - Mock tools for testing
|
|
@@ -1791,6 +1794,13 @@ declare function createToolSimulator(config: ToolSimulatorConfig): {
|
|
|
1791
1794
|
* ```
|
|
1792
1795
|
*/
|
|
1793
1796
|
|
|
1797
|
+
type RuntimeSchema<TInput = unknown> = z.ZodSchema<TInput>;
|
|
1798
|
+
type JsonSchemaObject = Record<string, unknown>;
|
|
1799
|
+
interface LangChainConvertibleTool<TInput = unknown, TOutput = unknown> {
|
|
1800
|
+
metadata: ToolMetadata;
|
|
1801
|
+
schema: RuntimeSchema<TInput>;
|
|
1802
|
+
invoke(input: TInput): Promise<TOutput>;
|
|
1803
|
+
}
|
|
1794
1804
|
/**
|
|
1795
1805
|
* Convert an AgentForge tool to a LangChain DynamicStructuredTool
|
|
1796
1806
|
*
|
|
@@ -1823,7 +1833,7 @@ declare function createToolSimulator(config: ToolSimulatorConfig): {
|
|
|
1823
1833
|
* });
|
|
1824
1834
|
* ```
|
|
1825
1835
|
*/
|
|
1826
|
-
declare function toLangChainTool(tool: Tool<
|
|
1836
|
+
declare function toLangChainTool<TInput, TOutput>(tool: Tool<TInput, TOutput>): DynamicStructuredTool<RuntimeSchema<TInput>, TInput, TInput, string>;
|
|
1827
1837
|
/**
|
|
1828
1838
|
* Convert multiple AgentForge tools to LangChain tools
|
|
1829
1839
|
*
|
|
@@ -1841,7 +1851,7 @@ declare function toLangChainTool(tool: Tool<any, any>): DynamicStructuredTool<an
|
|
|
1841
1851
|
* });
|
|
1842
1852
|
* ```
|
|
1843
1853
|
*/
|
|
1844
|
-
declare function toLangChainTools(tools:
|
|
1854
|
+
declare function toLangChainTools(tools: readonly LangChainConvertibleTool[]): DynamicStructuredTool[];
|
|
1845
1855
|
/**
|
|
1846
1856
|
* Get the JSON Schema representation of a tool's input schema
|
|
1847
1857
|
*
|
|
@@ -1856,7 +1866,7 @@ declare function toLangChainTools(tools: Tool<any, any>[]): DynamicStructuredToo
|
|
|
1856
1866
|
* console.log(JSON.stringify(schema, null, 2));
|
|
1857
1867
|
* ```
|
|
1858
1868
|
*/
|
|
1859
|
-
declare function getToolJsonSchema(tool: Tool<
|
|
1869
|
+
declare function getToolJsonSchema<TInput, TOutput>(tool: Tool<TInput, TOutput>): JsonSchemaObject;
|
|
1860
1870
|
/**
|
|
1861
1871
|
* Get tool metadata in a format suitable for LLM prompts
|
|
1862
1872
|
*
|
|
@@ -1877,7 +1887,7 @@ declare function getToolJsonSchema(tool: Tool<any, any>): Record<string, any>;
|
|
|
1877
1887
|
* // ...
|
|
1878
1888
|
* ```
|
|
1879
1889
|
*/
|
|
1880
|
-
declare function getToolDescription(tool: Tool<
|
|
1890
|
+
declare function getToolDescription<TInput, TOutput>(tool: Tool<TInput, TOutput>): string;
|
|
1881
1891
|
|
|
1882
1892
|
/**
|
|
1883
1893
|
* LangGraph State Utilities
|
package/dist/index.js
CHANGED
|
@@ -619,21 +619,42 @@ function toolBuilder() {
|
|
|
619
619
|
// src/langchain/converter.ts
|
|
620
620
|
import { DynamicStructuredTool } from "@langchain/core/tools";
|
|
621
621
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
622
|
+
function serializeToolResult(result) {
|
|
623
|
+
if (typeof result === "string") {
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
if (typeof result === "object" && result !== null) {
|
|
627
|
+
return JSON.stringify(result, null, 2);
|
|
628
|
+
}
|
|
629
|
+
return String(result);
|
|
630
|
+
}
|
|
631
|
+
function isJsonSchemaObject(value) {
|
|
632
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
633
|
+
}
|
|
634
|
+
function isJsonSchemaDefinitionMap(value) {
|
|
635
|
+
if (!isJsonSchemaObject(value)) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
return Object.values(value).every(isJsonSchemaObject);
|
|
639
|
+
}
|
|
640
|
+
function extractToolSchema(jsonSchema) {
|
|
641
|
+
if (!isJsonSchemaObject(jsonSchema)) {
|
|
642
|
+
return {};
|
|
643
|
+
}
|
|
644
|
+
const ref = jsonSchema.$ref;
|
|
645
|
+
const definitions = jsonSchema.definitions;
|
|
646
|
+
if (typeof ref !== "string" || !isJsonSchemaDefinitionMap(definitions)) {
|
|
647
|
+
return jsonSchema;
|
|
648
|
+
}
|
|
649
|
+
const refName = ref.replace("#/definitions/", "");
|
|
650
|
+
return definitions[refName] ?? jsonSchema;
|
|
651
|
+
}
|
|
622
652
|
function toLangChainTool(tool) {
|
|
623
653
|
return new DynamicStructuredTool({
|
|
624
654
|
name: tool.metadata.name,
|
|
625
655
|
description: tool.metadata.description,
|
|
626
656
|
schema: tool.schema,
|
|
627
|
-
func: async (input) =>
|
|
628
|
-
const result = await tool.invoke(input);
|
|
629
|
-
if (typeof result === "string") {
|
|
630
|
-
return result;
|
|
631
|
-
}
|
|
632
|
-
if (typeof result === "object" && result !== null) {
|
|
633
|
-
return JSON.stringify(result, null, 2);
|
|
634
|
-
}
|
|
635
|
-
return String(result);
|
|
636
|
-
}
|
|
657
|
+
func: async (input) => serializeToolResult(await tool.invoke(input))
|
|
637
658
|
});
|
|
638
659
|
}
|
|
639
660
|
function toLangChainTools(tools) {
|
|
@@ -645,11 +666,7 @@ function getToolJsonSchema(tool) {
|
|
|
645
666
|
$refStrategy: "none"
|
|
646
667
|
// Don't use $ref for nested schemas
|
|
647
668
|
});
|
|
648
|
-
|
|
649
|
-
const refName = jsonSchema.$ref.replace("#/definitions/", "");
|
|
650
|
-
return jsonSchema.definitions[refName] || jsonSchema;
|
|
651
|
-
}
|
|
652
|
-
return jsonSchema;
|
|
669
|
+
return extractToolSchema(jsonSchema);
|
|
653
670
|
}
|
|
654
671
|
function getToolDescription(tool) {
|
|
655
672
|
const { metadata } = tool;
|
|
@@ -1391,7 +1408,7 @@ function createToolExecutor(config = {}) {
|
|
|
1391
1408
|
}
|
|
1392
1409
|
return Math.min(delay, maxDelay);
|
|
1393
1410
|
}
|
|
1394
|
-
function
|
|
1411
|
+
function toError2(error) {
|
|
1395
1412
|
if (error instanceof Error) {
|
|
1396
1413
|
return error;
|
|
1397
1414
|
}
|
|
@@ -1422,7 +1439,7 @@ function createToolExecutor(config = {}) {
|
|
|
1422
1439
|
try {
|
|
1423
1440
|
return await executeFn.call(tool, input);
|
|
1424
1441
|
} catch (error) {
|
|
1425
|
-
const currentError =
|
|
1442
|
+
const currentError = toError2(error);
|
|
1426
1443
|
lastError = currentError;
|
|
1427
1444
|
if (policy.retryableErrors && policy.retryableErrors.length > 0) {
|
|
1428
1445
|
const isRetryable = policy.retryableErrors.some(
|
|
@@ -1460,7 +1477,7 @@ function createToolExecutor(config = {}) {
|
|
|
1460
1477
|
return result;
|
|
1461
1478
|
} catch (error) {
|
|
1462
1479
|
const duration = Date.now() - startTime;
|
|
1463
|
-
const normalizedError =
|
|
1480
|
+
const normalizedError = toError2(error);
|
|
1464
1481
|
metrics.totalExecutions++;
|
|
1465
1482
|
metrics.failedExecutions++;
|
|
1466
1483
|
metrics.totalDuration += duration;
|
|
@@ -1727,6 +1744,15 @@ function createManagedTool(config) {
|
|
|
1727
1744
|
}
|
|
1728
1745
|
|
|
1729
1746
|
// src/tools/composition.ts
|
|
1747
|
+
function isConditionalStep(step) {
|
|
1748
|
+
return !Array.isArray(step) && "condition" in step;
|
|
1749
|
+
}
|
|
1750
|
+
function calculateRetryDelay(attempt, delay, backoff) {
|
|
1751
|
+
return backoff === "exponential" ? delay * Math.pow(2, attempt - 1) : delay * attempt;
|
|
1752
|
+
}
|
|
1753
|
+
function toError(error) {
|
|
1754
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
1755
|
+
}
|
|
1730
1756
|
function sequential(tools) {
|
|
1731
1757
|
return {
|
|
1732
1758
|
name: `sequential(${tools.map((t) => t.name).join(" -> ")})`,
|
|
@@ -1770,7 +1796,7 @@ function composeTool(config) {
|
|
|
1770
1796
|
for (const step of config.steps) {
|
|
1771
1797
|
if (Array.isArray(step)) {
|
|
1772
1798
|
result = await parallel(step).invoke(result);
|
|
1773
|
-
} else if (
|
|
1799
|
+
} else if (isConditionalStep(step)) {
|
|
1774
1800
|
result = await conditional(step).invoke(result);
|
|
1775
1801
|
} else {
|
|
1776
1802
|
result = await step.invoke(result);
|
|
@@ -1785,18 +1811,21 @@ function composeTool(config) {
|
|
|
1785
1811
|
}
|
|
1786
1812
|
function retry(tool, options = {}) {
|
|
1787
1813
|
const { maxAttempts = 3, delay = 1e3, backoff = "exponential" } = options;
|
|
1814
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
|
|
1815
|
+
throw new Error("Invalid retry options: maxAttempts must be an integer >= 1");
|
|
1816
|
+
}
|
|
1788
1817
|
return {
|
|
1789
1818
|
name: `retry(${tool.name})`,
|
|
1790
1819
|
description: `${tool.description} (with retry)`,
|
|
1791
1820
|
invoke: async (input) => {
|
|
1792
|
-
let lastError;
|
|
1821
|
+
let lastError = new Error(`Tool ${tool.name} failed without an explicit error`);
|
|
1793
1822
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1794
1823
|
try {
|
|
1795
1824
|
return await tool.invoke(input);
|
|
1796
1825
|
} catch (error) {
|
|
1797
|
-
lastError = error;
|
|
1826
|
+
lastError = toError(error);
|
|
1798
1827
|
if (attempt < maxAttempts) {
|
|
1799
|
-
const waitTime =
|
|
1828
|
+
const waitTime = calculateRetryDelay(attempt, delay, backoff);
|
|
1800
1829
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
1801
1830
|
}
|
|
1802
1831
|
}
|
|
@@ -1810,12 +1839,19 @@ function timeout(tool, ms) {
|
|
|
1810
1839
|
name: `timeout(${tool.name})`,
|
|
1811
1840
|
description: `${tool.description} (with ${ms}ms timeout)`,
|
|
1812
1841
|
invoke: async (input) => {
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
)
|
|
1818
|
-
|
|
1842
|
+
let timer;
|
|
1843
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
1844
|
+
timer = setTimeout(() => {
|
|
1845
|
+
reject(new Error(`Tool ${tool.name} timed out after ${ms}ms`));
|
|
1846
|
+
}, ms);
|
|
1847
|
+
});
|
|
1848
|
+
try {
|
|
1849
|
+
return await Promise.race([tool.invoke(input), timeoutPromise]);
|
|
1850
|
+
} finally {
|
|
1851
|
+
if (timer !== void 0) {
|
|
1852
|
+
clearTimeout(timer);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1819
1855
|
}
|
|
1820
1856
|
};
|
|
1821
1857
|
}
|
package/package.json
CHANGED