@agentforge/core 0.16.43 → 0.16.45
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 +214 -200
- package/dist/index.d.cts +2 -53
- package/dist/index.d.ts +2 -53
- package/dist/index.js +214 -200
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1482,7 +1482,155 @@ function createToolExecutor(config = {}) {
|
|
|
1482
1482
|
};
|
|
1483
1483
|
}
|
|
1484
1484
|
|
|
1485
|
-
// src/tools/lifecycle.ts
|
|
1485
|
+
// src/tools/lifecycle-error.ts
|
|
1486
|
+
function getErrorMessage(error) {
|
|
1487
|
+
return error instanceof Error ? error.message : String(error);
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
// src/tools/lifecycle-health.ts
|
|
1491
|
+
function setHealthStats(state, result) {
|
|
1492
|
+
state.stats.lastHealthCheck = result;
|
|
1493
|
+
state.stats.lastHealthCheckTime = Date.now();
|
|
1494
|
+
}
|
|
1495
|
+
function isLifecycleStale(state, lifecycleGeneration) {
|
|
1496
|
+
return !state.initialized || state.cleaningUp || state.lifecycleGeneration !== lifecycleGeneration;
|
|
1497
|
+
}
|
|
1498
|
+
async function runManagedHealthCheck(state, healthCheckFn) {
|
|
1499
|
+
if (!state.initialized || state.cleaningUp) {
|
|
1500
|
+
return {
|
|
1501
|
+
healthy: false,
|
|
1502
|
+
error: "Tool is not initialized"
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
if (!healthCheckFn) {
|
|
1506
|
+
return {
|
|
1507
|
+
healthy: true,
|
|
1508
|
+
metadata: { message: "No health check configured" }
|
|
1509
|
+
};
|
|
1510
|
+
}
|
|
1511
|
+
const lifecycleGeneration = state.lifecycleGeneration;
|
|
1512
|
+
try {
|
|
1513
|
+
const result = await healthCheckFn();
|
|
1514
|
+
if (isLifecycleStale(state, lifecycleGeneration)) {
|
|
1515
|
+
return {
|
|
1516
|
+
healthy: false,
|
|
1517
|
+
error: "Tool is not initialized"
|
|
1518
|
+
};
|
|
1519
|
+
}
|
|
1520
|
+
setHealthStats(state, result);
|
|
1521
|
+
return result;
|
|
1522
|
+
} catch (error) {
|
|
1523
|
+
if (isLifecycleStale(state, lifecycleGeneration)) {
|
|
1524
|
+
return {
|
|
1525
|
+
healthy: false,
|
|
1526
|
+
error: "Tool is not initialized"
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
const result = {
|
|
1530
|
+
healthy: false,
|
|
1531
|
+
error: getErrorMessage(error)
|
|
1532
|
+
};
|
|
1533
|
+
setHealthStats(state, result);
|
|
1534
|
+
return result;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function runPeriodicManagedHealthCheck(state, healthCheckFn) {
|
|
1538
|
+
if (!healthCheckFn || state.healthCheckInFlight || !state.initialized || state.cleaningUp) {
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
state.healthCheckInFlight = true;
|
|
1542
|
+
const lifecycleGeneration = state.lifecycleGeneration;
|
|
1543
|
+
try {
|
|
1544
|
+
const result = await healthCheckFn();
|
|
1545
|
+
if (!isLifecycleStale(state, lifecycleGeneration)) {
|
|
1546
|
+
setHealthStats(state, result);
|
|
1547
|
+
}
|
|
1548
|
+
} catch (error) {
|
|
1549
|
+
if (!isLifecycleStale(state, lifecycleGeneration)) {
|
|
1550
|
+
setHealthStats(state, {
|
|
1551
|
+
healthy: false,
|
|
1552
|
+
error: getErrorMessage(error)
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
} finally {
|
|
1556
|
+
state.healthCheckInFlight = false;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
// src/tools/lifecycle-hooks.ts
|
|
1561
|
+
async function performManagedInitialize({
|
|
1562
|
+
ensureBeforeExitHandler,
|
|
1563
|
+
healthCheckFn,
|
|
1564
|
+
healthCheckInterval,
|
|
1565
|
+
initializeFn,
|
|
1566
|
+
runPeriodicHealthCheck,
|
|
1567
|
+
state
|
|
1568
|
+
}) {
|
|
1569
|
+
ensureBeforeExitHandler();
|
|
1570
|
+
state.lifecycleGeneration++;
|
|
1571
|
+
if (initializeFn) {
|
|
1572
|
+
await initializeFn();
|
|
1573
|
+
}
|
|
1574
|
+
state.initialized = true;
|
|
1575
|
+
state.stats.initialized = true;
|
|
1576
|
+
if (healthCheckInterval && healthCheckFn) {
|
|
1577
|
+
state.healthCheckTimer = setInterval(() => {
|
|
1578
|
+
void runPeriodicHealthCheck();
|
|
1579
|
+
}, healthCheckInterval);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
async function performManagedCleanup({
|
|
1583
|
+
cleanupFn,
|
|
1584
|
+
state
|
|
1585
|
+
}) {
|
|
1586
|
+
state.cleaningUp = true;
|
|
1587
|
+
if (state.healthCheckTimer) {
|
|
1588
|
+
clearInterval(state.healthCheckTimer);
|
|
1589
|
+
state.healthCheckTimer = void 0;
|
|
1590
|
+
}
|
|
1591
|
+
if (state.beforeExitHandler) {
|
|
1592
|
+
process.off("beforeExit", state.beforeExitHandler);
|
|
1593
|
+
state.beforeExitHandler = void 0;
|
|
1594
|
+
}
|
|
1595
|
+
if (!state.initialized) {
|
|
1596
|
+
state.cleaningUp = false;
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
state.initialized = false;
|
|
1600
|
+
state.stats.initialized = false;
|
|
1601
|
+
if (cleanupFn) {
|
|
1602
|
+
try {
|
|
1603
|
+
await cleanupFn();
|
|
1604
|
+
} finally {
|
|
1605
|
+
state.cleaningUp = false;
|
|
1606
|
+
}
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
state.cleaningUp = false;
|
|
1610
|
+
}
|
|
1611
|
+
function ensureManagedBeforeExitHandler({
|
|
1612
|
+
autoCleanup,
|
|
1613
|
+
cleanup,
|
|
1614
|
+
logger: logger6,
|
|
1615
|
+
name,
|
|
1616
|
+
state
|
|
1617
|
+
}) {
|
|
1618
|
+
if (!autoCleanup || state.beforeExitHandler) {
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
state.beforeExitHandler = () => {
|
|
1622
|
+
cleanup().catch(
|
|
1623
|
+
(err) => logger6.error("Cleanup failed", {
|
|
1624
|
+
toolName: name,
|
|
1625
|
+
error: getErrorMessage(err),
|
|
1626
|
+
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
1627
|
+
})
|
|
1628
|
+
);
|
|
1629
|
+
};
|
|
1630
|
+
process.on("beforeExit", state.beforeExitHandler);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
// src/tools/lifecycle-managed-tool.ts
|
|
1486
1634
|
var logger3 = createLogger("agentforge:core:tools:lifecycle", { level: "info" /* INFO */ });
|
|
1487
1635
|
var ManagedTool = class {
|
|
1488
1636
|
name;
|
|
@@ -1493,21 +1641,7 @@ var ManagedTool = class {
|
|
|
1493
1641
|
healthCheckFn;
|
|
1494
1642
|
autoCleanup;
|
|
1495
1643
|
healthCheckInterval;
|
|
1496
|
-
|
|
1497
|
-
_context;
|
|
1498
|
-
_stats = {
|
|
1499
|
-
initialized: false,
|
|
1500
|
-
totalExecutions: 0,
|
|
1501
|
-
successfulExecutions: 0,
|
|
1502
|
-
failedExecutions: 0
|
|
1503
|
-
};
|
|
1504
|
-
_healthCheckTimer;
|
|
1505
|
-
_beforeExitHandler;
|
|
1506
|
-
_healthCheckInFlight = false;
|
|
1507
|
-
_cleaningUp = false;
|
|
1508
|
-
_cleanupPromise;
|
|
1509
|
-
_initializePromise;
|
|
1510
|
-
_lifecycleGeneration = 0;
|
|
1644
|
+
state;
|
|
1511
1645
|
constructor(config) {
|
|
1512
1646
|
this.name = config.name;
|
|
1513
1647
|
this.description = config.description;
|
|
@@ -1517,254 +1651,134 @@ var ManagedTool = class {
|
|
|
1517
1651
|
this.healthCheckFn = config.healthCheck?.bind(this);
|
|
1518
1652
|
this.autoCleanup = config.autoCleanup ?? true;
|
|
1519
1653
|
this.healthCheckInterval = config.healthCheckInterval;
|
|
1520
|
-
this.
|
|
1654
|
+
this.state = {
|
|
1655
|
+
initialized: false,
|
|
1656
|
+
context: config.context,
|
|
1657
|
+
stats: {
|
|
1658
|
+
initialized: false,
|
|
1659
|
+
totalExecutions: 0,
|
|
1660
|
+
successfulExecutions: 0,
|
|
1661
|
+
failedExecutions: 0
|
|
1662
|
+
},
|
|
1663
|
+
healthCheckInFlight: false,
|
|
1664
|
+
cleaningUp: false,
|
|
1665
|
+
lifecycleGeneration: 0
|
|
1666
|
+
};
|
|
1521
1667
|
this.ensureBeforeExitHandler();
|
|
1522
1668
|
}
|
|
1523
|
-
/**
|
|
1524
|
-
* Get the tool context (e.g., connection pool, API client)
|
|
1525
|
-
*/
|
|
1526
1669
|
get context() {
|
|
1527
|
-
return this.
|
|
1670
|
+
return this.state.context;
|
|
1528
1671
|
}
|
|
1529
|
-
/**
|
|
1530
|
-
* Set the tool context
|
|
1531
|
-
*/
|
|
1532
1672
|
set context(value) {
|
|
1533
|
-
this.
|
|
1673
|
+
this.state.context = value;
|
|
1534
1674
|
}
|
|
1535
|
-
/**
|
|
1536
|
-
* Check if tool is initialized
|
|
1537
|
-
*/
|
|
1538
1675
|
get initialized() {
|
|
1539
|
-
return this.
|
|
1676
|
+
return this.state.initialized;
|
|
1540
1677
|
}
|
|
1541
|
-
/**
|
|
1542
|
-
* Initialize the tool
|
|
1543
|
-
*/
|
|
1544
1678
|
async initialize() {
|
|
1545
|
-
if (this.
|
|
1546
|
-
await this.
|
|
1679
|
+
if (this.state.initializePromise) {
|
|
1680
|
+
await this.state.initializePromise;
|
|
1547
1681
|
return;
|
|
1548
1682
|
}
|
|
1549
|
-
if (this.
|
|
1550
|
-
await this.
|
|
1551
|
-
if (this.
|
|
1552
|
-
await this.
|
|
1683
|
+
if (this.state.cleanupPromise) {
|
|
1684
|
+
await this.state.cleanupPromise;
|
|
1685
|
+
if (this.state.initializePromise) {
|
|
1686
|
+
await this.state.initializePromise;
|
|
1553
1687
|
return;
|
|
1554
1688
|
}
|
|
1555
1689
|
}
|
|
1556
|
-
if (this.
|
|
1690
|
+
if (this.state.initialized) {
|
|
1557
1691
|
return;
|
|
1558
1692
|
}
|
|
1559
|
-
const initializePromise =
|
|
1560
|
-
|
|
1693
|
+
const initializePromise = performManagedInitialize({
|
|
1694
|
+
ensureBeforeExitHandler: () => this.ensureBeforeExitHandler(),
|
|
1695
|
+
healthCheckFn: this.healthCheckFn,
|
|
1696
|
+
healthCheckInterval: this.healthCheckInterval,
|
|
1697
|
+
initializeFn: this.initializeFn,
|
|
1698
|
+
runPeriodicHealthCheck: () => this.runPeriodicHealthCheck(),
|
|
1699
|
+
state: this.state
|
|
1700
|
+
});
|
|
1701
|
+
this.state.initializePromise = initializePromise;
|
|
1561
1702
|
try {
|
|
1562
1703
|
await initializePromise;
|
|
1563
1704
|
} finally {
|
|
1564
|
-
this.
|
|
1705
|
+
this.state.initializePromise = void 0;
|
|
1565
1706
|
}
|
|
1566
1707
|
}
|
|
1567
|
-
/**
|
|
1568
|
-
* Execute the tool
|
|
1569
|
-
*/
|
|
1570
1708
|
async execute(input) {
|
|
1571
|
-
if (!this.
|
|
1709
|
+
if (!this.state.initialized) {
|
|
1572
1710
|
throw new Error(`Tool ${this.name} is not initialized. Call initialize() first.`);
|
|
1573
1711
|
}
|
|
1574
1712
|
const startTime = Date.now();
|
|
1575
|
-
this.
|
|
1713
|
+
this.state.stats.totalExecutions++;
|
|
1576
1714
|
try {
|
|
1577
1715
|
const result = await this.executeFn(input);
|
|
1578
|
-
this.
|
|
1579
|
-
this.
|
|
1716
|
+
this.state.stats.successfulExecutions++;
|
|
1717
|
+
this.state.stats.lastExecutionTime = Date.now() - startTime;
|
|
1580
1718
|
return result;
|
|
1581
1719
|
} catch (error) {
|
|
1582
|
-
this.
|
|
1583
|
-
this.
|
|
1720
|
+
this.state.stats.failedExecutions++;
|
|
1721
|
+
this.state.stats.lastExecutionTime = Date.now() - startTime;
|
|
1584
1722
|
throw error;
|
|
1585
1723
|
}
|
|
1586
1724
|
}
|
|
1587
|
-
/**
|
|
1588
|
-
* Cleanup the tool
|
|
1589
|
-
*/
|
|
1590
1725
|
async cleanup() {
|
|
1591
|
-
if (this.
|
|
1592
|
-
await this.
|
|
1726
|
+
if (this.state.cleanupPromise) {
|
|
1727
|
+
await this.state.cleanupPromise;
|
|
1593
1728
|
return;
|
|
1594
1729
|
}
|
|
1595
|
-
if (this.
|
|
1730
|
+
if (this.state.initializePromise) {
|
|
1596
1731
|
try {
|
|
1597
|
-
await this.
|
|
1732
|
+
await this.state.initializePromise;
|
|
1598
1733
|
} catch {
|
|
1599
1734
|
}
|
|
1600
1735
|
}
|
|
1601
|
-
const cleanupPromise =
|
|
1602
|
-
|
|
1736
|
+
const cleanupPromise = performManagedCleanup({
|
|
1737
|
+
cleanupFn: this.cleanupFn,
|
|
1738
|
+
state: this.state
|
|
1739
|
+
});
|
|
1740
|
+
this.state.cleanupPromise = cleanupPromise;
|
|
1603
1741
|
try {
|
|
1604
1742
|
await cleanupPromise;
|
|
1605
1743
|
} finally {
|
|
1606
|
-
this.
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
async performCleanup() {
|
|
1610
|
-
this._cleaningUp = true;
|
|
1611
|
-
if (this._healthCheckTimer) {
|
|
1612
|
-
clearInterval(this._healthCheckTimer);
|
|
1613
|
-
this._healthCheckTimer = void 0;
|
|
1614
|
-
}
|
|
1615
|
-
if (this._beforeExitHandler) {
|
|
1616
|
-
process.off("beforeExit", this._beforeExitHandler);
|
|
1617
|
-
this._beforeExitHandler = void 0;
|
|
1618
|
-
}
|
|
1619
|
-
if (!this._initialized) {
|
|
1620
|
-
this._cleaningUp = false;
|
|
1621
|
-
return;
|
|
1744
|
+
this.state.cleanupPromise = void 0;
|
|
1622
1745
|
}
|
|
1623
|
-
this._initialized = false;
|
|
1624
|
-
this._stats.initialized = false;
|
|
1625
|
-
if (this.cleanupFn) {
|
|
1626
|
-
try {
|
|
1627
|
-
await this.cleanupFn();
|
|
1628
|
-
} finally {
|
|
1629
|
-
this._cleaningUp = false;
|
|
1630
|
-
}
|
|
1631
|
-
return;
|
|
1632
|
-
}
|
|
1633
|
-
this._cleaningUp = false;
|
|
1634
1746
|
}
|
|
1635
|
-
/**
|
|
1636
|
-
* Run health check
|
|
1637
|
-
*/
|
|
1638
1747
|
async healthCheck() {
|
|
1639
|
-
|
|
1640
|
-
return {
|
|
1641
|
-
healthy: false,
|
|
1642
|
-
error: "Tool is not initialized"
|
|
1643
|
-
};
|
|
1644
|
-
}
|
|
1645
|
-
if (!this.healthCheckFn) {
|
|
1646
|
-
return {
|
|
1647
|
-
healthy: true,
|
|
1648
|
-
metadata: { message: "No health check configured" }
|
|
1649
|
-
};
|
|
1650
|
-
}
|
|
1651
|
-
const lifecycleGeneration = this._lifecycleGeneration;
|
|
1652
|
-
try {
|
|
1653
|
-
const result = await this.healthCheckFn();
|
|
1654
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1655
|
-
return {
|
|
1656
|
-
healthy: false,
|
|
1657
|
-
error: "Tool is not initialized"
|
|
1658
|
-
};
|
|
1659
|
-
}
|
|
1660
|
-
this._stats.lastHealthCheck = result;
|
|
1661
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1662
|
-
return result;
|
|
1663
|
-
} catch (error) {
|
|
1664
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1665
|
-
return {
|
|
1666
|
-
healthy: false,
|
|
1667
|
-
error: "Tool is not initialized"
|
|
1668
|
-
};
|
|
1669
|
-
}
|
|
1670
|
-
const result = {
|
|
1671
|
-
healthy: false,
|
|
1672
|
-
error: getErrorMessage(error)
|
|
1673
|
-
};
|
|
1674
|
-
this._stats.lastHealthCheck = result;
|
|
1675
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1676
|
-
return result;
|
|
1677
|
-
}
|
|
1748
|
+
return runManagedHealthCheck(this.state, this.healthCheckFn);
|
|
1678
1749
|
}
|
|
1679
|
-
/**
|
|
1680
|
-
* Get tool statistics
|
|
1681
|
-
*/
|
|
1682
1750
|
getStats() {
|
|
1683
|
-
return { ...this.
|
|
1751
|
+
return { ...this.state.stats };
|
|
1684
1752
|
}
|
|
1685
|
-
/**
|
|
1686
|
-
* Reset statistics
|
|
1687
|
-
*/
|
|
1688
1753
|
resetStats() {
|
|
1689
|
-
this.
|
|
1690
|
-
this.
|
|
1691
|
-
this.
|
|
1692
|
-
this.
|
|
1754
|
+
this.state.stats.totalExecutions = 0;
|
|
1755
|
+
this.state.stats.successfulExecutions = 0;
|
|
1756
|
+
this.state.stats.failedExecutions = 0;
|
|
1757
|
+
this.state.stats.lastExecutionTime = void 0;
|
|
1693
1758
|
}
|
|
1694
|
-
/**
|
|
1695
|
-
* Convert to LangChain tool format
|
|
1696
|
-
*/
|
|
1697
1759
|
toLangChainTool() {
|
|
1698
1760
|
return {
|
|
1699
1761
|
name: this.name,
|
|
1700
1762
|
description: this.description,
|
|
1701
|
-
invoke: async (input) =>
|
|
1702
|
-
return await this.execute(input);
|
|
1703
|
-
}
|
|
1763
|
+
invoke: async (input) => this.execute(input)
|
|
1704
1764
|
};
|
|
1705
1765
|
}
|
|
1706
1766
|
async runPeriodicHealthCheck() {
|
|
1707
|
-
|
|
1708
|
-
return;
|
|
1709
|
-
}
|
|
1710
|
-
this._healthCheckInFlight = true;
|
|
1711
|
-
const lifecycleGeneration = this._lifecycleGeneration;
|
|
1712
|
-
try {
|
|
1713
|
-
const result = await this.healthCheckFn();
|
|
1714
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
this._stats.lastHealthCheck = result;
|
|
1718
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1719
|
-
} catch (error) {
|
|
1720
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1721
|
-
return;
|
|
1722
|
-
}
|
|
1723
|
-
this._stats.lastHealthCheck = {
|
|
1724
|
-
healthy: false,
|
|
1725
|
-
error: getErrorMessage(error)
|
|
1726
|
-
};
|
|
1727
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1728
|
-
} finally {
|
|
1729
|
-
this._healthCheckInFlight = false;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
async performInitialize() {
|
|
1733
|
-
this.ensureBeforeExitHandler();
|
|
1734
|
-
this._lifecycleGeneration++;
|
|
1735
|
-
if (this.initializeFn) {
|
|
1736
|
-
await this.initializeFn();
|
|
1737
|
-
}
|
|
1738
|
-
this._initialized = true;
|
|
1739
|
-
this._stats.initialized = true;
|
|
1740
|
-
if (this.healthCheckInterval && this.healthCheckFn) {
|
|
1741
|
-
this._healthCheckTimer = setInterval(() => {
|
|
1742
|
-
void this.runPeriodicHealthCheck();
|
|
1743
|
-
}, this.healthCheckInterval);
|
|
1744
|
-
}
|
|
1767
|
+
await runPeriodicManagedHealthCheck(this.state, this.healthCheckFn);
|
|
1745
1768
|
}
|
|
1746
1769
|
ensureBeforeExitHandler() {
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
this.
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
error: getErrorMessage(err),
|
|
1755
|
-
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
1756
|
-
})
|
|
1757
|
-
);
|
|
1758
|
-
};
|
|
1759
|
-
process.on("beforeExit", this._beforeExitHandler);
|
|
1770
|
+
ensureManagedBeforeExitHandler({
|
|
1771
|
+
autoCleanup: this.autoCleanup,
|
|
1772
|
+
cleanup: () => this.cleanup(),
|
|
1773
|
+
logger: logger3,
|
|
1774
|
+
name: this.name,
|
|
1775
|
+
state: this.state
|
|
1776
|
+
});
|
|
1760
1777
|
}
|
|
1761
1778
|
};
|
|
1762
1779
|
function createManagedTool(config) {
|
|
1763
1780
|
return new ManagedTool(config);
|
|
1764
1781
|
}
|
|
1765
|
-
function getErrorMessage(error) {
|
|
1766
|
-
return error instanceof Error ? error.message : String(error);
|
|
1767
|
-
}
|
|
1768
1782
|
|
|
1769
1783
|
// src/tools/composition.ts
|
|
1770
1784
|
function isConditionalStep(step) {
|
package/dist/index.d.cts
CHANGED
|
@@ -1077,11 +1077,6 @@ interface JsonObject {
|
|
|
1077
1077
|
[key: string]: JsonValue;
|
|
1078
1078
|
}
|
|
1079
1079
|
|
|
1080
|
-
/**
|
|
1081
|
-
* Tool Lifecycle Management - Manage tool initialization, cleanup, and resources
|
|
1082
|
-
* @module tools/lifecycle
|
|
1083
|
-
*/
|
|
1084
|
-
|
|
1085
1080
|
interface ToolHealthCheckResult {
|
|
1086
1081
|
healthy: boolean;
|
|
1087
1082
|
error?: string;
|
|
@@ -1109,9 +1104,7 @@ interface ManagedToolStats {
|
|
|
1109
1104
|
lastHealthCheck?: ToolHealthCheckResult;
|
|
1110
1105
|
lastHealthCheckTime?: number;
|
|
1111
1106
|
}
|
|
1112
|
-
|
|
1113
|
-
* Managed tool with lifecycle hooks
|
|
1114
|
-
*/
|
|
1107
|
+
|
|
1115
1108
|
declare class ManagedTool<TContext = undefined, TInput = unknown, TOutput = unknown> {
|
|
1116
1109
|
readonly name: string;
|
|
1117
1110
|
readonly description: string;
|
|
@@ -1121,69 +1114,25 @@ declare class ManagedTool<TContext = undefined, TInput = unknown, TOutput = unkn
|
|
|
1121
1114
|
private readonly healthCheckFn?;
|
|
1122
1115
|
private readonly autoCleanup;
|
|
1123
1116
|
private readonly healthCheckInterval?;
|
|
1124
|
-
private
|
|
1125
|
-
private _context;
|
|
1126
|
-
private _stats;
|
|
1127
|
-
private _healthCheckTimer?;
|
|
1128
|
-
private _beforeExitHandler?;
|
|
1129
|
-
private _healthCheckInFlight;
|
|
1130
|
-
private _cleaningUp;
|
|
1131
|
-
private _cleanupPromise?;
|
|
1132
|
-
private _initializePromise?;
|
|
1133
|
-
private _lifecycleGeneration;
|
|
1117
|
+
private readonly state;
|
|
1134
1118
|
constructor(config: ManagedToolConfig<TContext, TInput, TOutput>);
|
|
1135
|
-
/**
|
|
1136
|
-
* Get the tool context (e.g., connection pool, API client)
|
|
1137
|
-
*/
|
|
1138
1119
|
get context(): TContext | undefined;
|
|
1139
|
-
/**
|
|
1140
|
-
* Set the tool context
|
|
1141
|
-
*/
|
|
1142
1120
|
set context(value: TContext | undefined);
|
|
1143
|
-
/**
|
|
1144
|
-
* Check if tool is initialized
|
|
1145
|
-
*/
|
|
1146
1121
|
get initialized(): boolean;
|
|
1147
|
-
/**
|
|
1148
|
-
* Initialize the tool
|
|
1149
|
-
*/
|
|
1150
1122
|
initialize(): Promise<void>;
|
|
1151
|
-
/**
|
|
1152
|
-
* Execute the tool
|
|
1153
|
-
*/
|
|
1154
1123
|
execute(input: TInput): Promise<TOutput>;
|
|
1155
|
-
/**
|
|
1156
|
-
* Cleanup the tool
|
|
1157
|
-
*/
|
|
1158
1124
|
cleanup(): Promise<void>;
|
|
1159
|
-
private performCleanup;
|
|
1160
|
-
/**
|
|
1161
|
-
* Run health check
|
|
1162
|
-
*/
|
|
1163
1125
|
healthCheck(): Promise<ToolHealthCheckResult>;
|
|
1164
|
-
/**
|
|
1165
|
-
* Get tool statistics
|
|
1166
|
-
*/
|
|
1167
1126
|
getStats(): ManagedToolStats;
|
|
1168
|
-
/**
|
|
1169
|
-
* Reset statistics
|
|
1170
|
-
*/
|
|
1171
1127
|
resetStats(): void;
|
|
1172
|
-
/**
|
|
1173
|
-
* Convert to LangChain tool format
|
|
1174
|
-
*/
|
|
1175
1128
|
toLangChainTool(): {
|
|
1176
1129
|
name: string;
|
|
1177
1130
|
description: string;
|
|
1178
1131
|
invoke: (input: TInput) => Promise<TOutput>;
|
|
1179
1132
|
};
|
|
1180
1133
|
private runPeriodicHealthCheck;
|
|
1181
|
-
private performInitialize;
|
|
1182
1134
|
private ensureBeforeExitHandler;
|
|
1183
1135
|
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Create a managed tool
|
|
1186
|
-
*/
|
|
1187
1136
|
declare function createManagedTool<TContext = undefined, TInput = unknown, TOutput = unknown>(config: ManagedToolConfig<TContext, TInput, TOutput>): ManagedTool<TContext, TInput, TOutput>;
|
|
1188
1137
|
|
|
1189
1138
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1077,11 +1077,6 @@ interface JsonObject {
|
|
|
1077
1077
|
[key: string]: JsonValue;
|
|
1078
1078
|
}
|
|
1079
1079
|
|
|
1080
|
-
/**
|
|
1081
|
-
* Tool Lifecycle Management - Manage tool initialization, cleanup, and resources
|
|
1082
|
-
* @module tools/lifecycle
|
|
1083
|
-
*/
|
|
1084
|
-
|
|
1085
1080
|
interface ToolHealthCheckResult {
|
|
1086
1081
|
healthy: boolean;
|
|
1087
1082
|
error?: string;
|
|
@@ -1109,9 +1104,7 @@ interface ManagedToolStats {
|
|
|
1109
1104
|
lastHealthCheck?: ToolHealthCheckResult;
|
|
1110
1105
|
lastHealthCheckTime?: number;
|
|
1111
1106
|
}
|
|
1112
|
-
|
|
1113
|
-
* Managed tool with lifecycle hooks
|
|
1114
|
-
*/
|
|
1107
|
+
|
|
1115
1108
|
declare class ManagedTool<TContext = undefined, TInput = unknown, TOutput = unknown> {
|
|
1116
1109
|
readonly name: string;
|
|
1117
1110
|
readonly description: string;
|
|
@@ -1121,69 +1114,25 @@ declare class ManagedTool<TContext = undefined, TInput = unknown, TOutput = unkn
|
|
|
1121
1114
|
private readonly healthCheckFn?;
|
|
1122
1115
|
private readonly autoCleanup;
|
|
1123
1116
|
private readonly healthCheckInterval?;
|
|
1124
|
-
private
|
|
1125
|
-
private _context;
|
|
1126
|
-
private _stats;
|
|
1127
|
-
private _healthCheckTimer?;
|
|
1128
|
-
private _beforeExitHandler?;
|
|
1129
|
-
private _healthCheckInFlight;
|
|
1130
|
-
private _cleaningUp;
|
|
1131
|
-
private _cleanupPromise?;
|
|
1132
|
-
private _initializePromise?;
|
|
1133
|
-
private _lifecycleGeneration;
|
|
1117
|
+
private readonly state;
|
|
1134
1118
|
constructor(config: ManagedToolConfig<TContext, TInput, TOutput>);
|
|
1135
|
-
/**
|
|
1136
|
-
* Get the tool context (e.g., connection pool, API client)
|
|
1137
|
-
*/
|
|
1138
1119
|
get context(): TContext | undefined;
|
|
1139
|
-
/**
|
|
1140
|
-
* Set the tool context
|
|
1141
|
-
*/
|
|
1142
1120
|
set context(value: TContext | undefined);
|
|
1143
|
-
/**
|
|
1144
|
-
* Check if tool is initialized
|
|
1145
|
-
*/
|
|
1146
1121
|
get initialized(): boolean;
|
|
1147
|
-
/**
|
|
1148
|
-
* Initialize the tool
|
|
1149
|
-
*/
|
|
1150
1122
|
initialize(): Promise<void>;
|
|
1151
|
-
/**
|
|
1152
|
-
* Execute the tool
|
|
1153
|
-
*/
|
|
1154
1123
|
execute(input: TInput): Promise<TOutput>;
|
|
1155
|
-
/**
|
|
1156
|
-
* Cleanup the tool
|
|
1157
|
-
*/
|
|
1158
1124
|
cleanup(): Promise<void>;
|
|
1159
|
-
private performCleanup;
|
|
1160
|
-
/**
|
|
1161
|
-
* Run health check
|
|
1162
|
-
*/
|
|
1163
1125
|
healthCheck(): Promise<ToolHealthCheckResult>;
|
|
1164
|
-
/**
|
|
1165
|
-
* Get tool statistics
|
|
1166
|
-
*/
|
|
1167
1126
|
getStats(): ManagedToolStats;
|
|
1168
|
-
/**
|
|
1169
|
-
* Reset statistics
|
|
1170
|
-
*/
|
|
1171
1127
|
resetStats(): void;
|
|
1172
|
-
/**
|
|
1173
|
-
* Convert to LangChain tool format
|
|
1174
|
-
*/
|
|
1175
1128
|
toLangChainTool(): {
|
|
1176
1129
|
name: string;
|
|
1177
1130
|
description: string;
|
|
1178
1131
|
invoke: (input: TInput) => Promise<TOutput>;
|
|
1179
1132
|
};
|
|
1180
1133
|
private runPeriodicHealthCheck;
|
|
1181
|
-
private performInitialize;
|
|
1182
1134
|
private ensureBeforeExitHandler;
|
|
1183
1135
|
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Create a managed tool
|
|
1186
|
-
*/
|
|
1187
1136
|
declare function createManagedTool<TContext = undefined, TInput = unknown, TOutput = unknown>(config: ManagedToolConfig<TContext, TInput, TOutput>): ManagedTool<TContext, TInput, TOutput>;
|
|
1188
1137
|
|
|
1189
1138
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1307,7 +1307,155 @@ function createToolExecutor(config = {}) {
|
|
|
1307
1307
|
};
|
|
1308
1308
|
}
|
|
1309
1309
|
|
|
1310
|
-
// src/tools/lifecycle.ts
|
|
1310
|
+
// src/tools/lifecycle-error.ts
|
|
1311
|
+
function getErrorMessage(error) {
|
|
1312
|
+
return error instanceof Error ? error.message : String(error);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// src/tools/lifecycle-health.ts
|
|
1316
|
+
function setHealthStats(state, result) {
|
|
1317
|
+
state.stats.lastHealthCheck = result;
|
|
1318
|
+
state.stats.lastHealthCheckTime = Date.now();
|
|
1319
|
+
}
|
|
1320
|
+
function isLifecycleStale(state, lifecycleGeneration) {
|
|
1321
|
+
return !state.initialized || state.cleaningUp || state.lifecycleGeneration !== lifecycleGeneration;
|
|
1322
|
+
}
|
|
1323
|
+
async function runManagedHealthCheck(state, healthCheckFn) {
|
|
1324
|
+
if (!state.initialized || state.cleaningUp) {
|
|
1325
|
+
return {
|
|
1326
|
+
healthy: false,
|
|
1327
|
+
error: "Tool is not initialized"
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
if (!healthCheckFn) {
|
|
1331
|
+
return {
|
|
1332
|
+
healthy: true,
|
|
1333
|
+
metadata: { message: "No health check configured" }
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
const lifecycleGeneration = state.lifecycleGeneration;
|
|
1337
|
+
try {
|
|
1338
|
+
const result = await healthCheckFn();
|
|
1339
|
+
if (isLifecycleStale(state, lifecycleGeneration)) {
|
|
1340
|
+
return {
|
|
1341
|
+
healthy: false,
|
|
1342
|
+
error: "Tool is not initialized"
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
setHealthStats(state, result);
|
|
1346
|
+
return result;
|
|
1347
|
+
} catch (error) {
|
|
1348
|
+
if (isLifecycleStale(state, lifecycleGeneration)) {
|
|
1349
|
+
return {
|
|
1350
|
+
healthy: false,
|
|
1351
|
+
error: "Tool is not initialized"
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
const result = {
|
|
1355
|
+
healthy: false,
|
|
1356
|
+
error: getErrorMessage(error)
|
|
1357
|
+
};
|
|
1358
|
+
setHealthStats(state, result);
|
|
1359
|
+
return result;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
async function runPeriodicManagedHealthCheck(state, healthCheckFn) {
|
|
1363
|
+
if (!healthCheckFn || state.healthCheckInFlight || !state.initialized || state.cleaningUp) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
state.healthCheckInFlight = true;
|
|
1367
|
+
const lifecycleGeneration = state.lifecycleGeneration;
|
|
1368
|
+
try {
|
|
1369
|
+
const result = await healthCheckFn();
|
|
1370
|
+
if (!isLifecycleStale(state, lifecycleGeneration)) {
|
|
1371
|
+
setHealthStats(state, result);
|
|
1372
|
+
}
|
|
1373
|
+
} catch (error) {
|
|
1374
|
+
if (!isLifecycleStale(state, lifecycleGeneration)) {
|
|
1375
|
+
setHealthStats(state, {
|
|
1376
|
+
healthy: false,
|
|
1377
|
+
error: getErrorMessage(error)
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
} finally {
|
|
1381
|
+
state.healthCheckInFlight = false;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// src/tools/lifecycle-hooks.ts
|
|
1386
|
+
async function performManagedInitialize({
|
|
1387
|
+
ensureBeforeExitHandler,
|
|
1388
|
+
healthCheckFn,
|
|
1389
|
+
healthCheckInterval,
|
|
1390
|
+
initializeFn,
|
|
1391
|
+
runPeriodicHealthCheck,
|
|
1392
|
+
state
|
|
1393
|
+
}) {
|
|
1394
|
+
ensureBeforeExitHandler();
|
|
1395
|
+
state.lifecycleGeneration++;
|
|
1396
|
+
if (initializeFn) {
|
|
1397
|
+
await initializeFn();
|
|
1398
|
+
}
|
|
1399
|
+
state.initialized = true;
|
|
1400
|
+
state.stats.initialized = true;
|
|
1401
|
+
if (healthCheckInterval && healthCheckFn) {
|
|
1402
|
+
state.healthCheckTimer = setInterval(() => {
|
|
1403
|
+
void runPeriodicHealthCheck();
|
|
1404
|
+
}, healthCheckInterval);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
async function performManagedCleanup({
|
|
1408
|
+
cleanupFn,
|
|
1409
|
+
state
|
|
1410
|
+
}) {
|
|
1411
|
+
state.cleaningUp = true;
|
|
1412
|
+
if (state.healthCheckTimer) {
|
|
1413
|
+
clearInterval(state.healthCheckTimer);
|
|
1414
|
+
state.healthCheckTimer = void 0;
|
|
1415
|
+
}
|
|
1416
|
+
if (state.beforeExitHandler) {
|
|
1417
|
+
process.off("beforeExit", state.beforeExitHandler);
|
|
1418
|
+
state.beforeExitHandler = void 0;
|
|
1419
|
+
}
|
|
1420
|
+
if (!state.initialized) {
|
|
1421
|
+
state.cleaningUp = false;
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
state.initialized = false;
|
|
1425
|
+
state.stats.initialized = false;
|
|
1426
|
+
if (cleanupFn) {
|
|
1427
|
+
try {
|
|
1428
|
+
await cleanupFn();
|
|
1429
|
+
} finally {
|
|
1430
|
+
state.cleaningUp = false;
|
|
1431
|
+
}
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
state.cleaningUp = false;
|
|
1435
|
+
}
|
|
1436
|
+
function ensureManagedBeforeExitHandler({
|
|
1437
|
+
autoCleanup,
|
|
1438
|
+
cleanup,
|
|
1439
|
+
logger: logger6,
|
|
1440
|
+
name,
|
|
1441
|
+
state
|
|
1442
|
+
}) {
|
|
1443
|
+
if (!autoCleanup || state.beforeExitHandler) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
state.beforeExitHandler = () => {
|
|
1447
|
+
cleanup().catch(
|
|
1448
|
+
(err) => logger6.error("Cleanup failed", {
|
|
1449
|
+
toolName: name,
|
|
1450
|
+
error: getErrorMessage(err),
|
|
1451
|
+
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
1452
|
+
})
|
|
1453
|
+
);
|
|
1454
|
+
};
|
|
1455
|
+
process.on("beforeExit", state.beforeExitHandler);
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// src/tools/lifecycle-managed-tool.ts
|
|
1311
1459
|
var logger3 = createLogger("agentforge:core:tools:lifecycle", { level: "info" /* INFO */ });
|
|
1312
1460
|
var ManagedTool = class {
|
|
1313
1461
|
name;
|
|
@@ -1318,21 +1466,7 @@ var ManagedTool = class {
|
|
|
1318
1466
|
healthCheckFn;
|
|
1319
1467
|
autoCleanup;
|
|
1320
1468
|
healthCheckInterval;
|
|
1321
|
-
|
|
1322
|
-
_context;
|
|
1323
|
-
_stats = {
|
|
1324
|
-
initialized: false,
|
|
1325
|
-
totalExecutions: 0,
|
|
1326
|
-
successfulExecutions: 0,
|
|
1327
|
-
failedExecutions: 0
|
|
1328
|
-
};
|
|
1329
|
-
_healthCheckTimer;
|
|
1330
|
-
_beforeExitHandler;
|
|
1331
|
-
_healthCheckInFlight = false;
|
|
1332
|
-
_cleaningUp = false;
|
|
1333
|
-
_cleanupPromise;
|
|
1334
|
-
_initializePromise;
|
|
1335
|
-
_lifecycleGeneration = 0;
|
|
1469
|
+
state;
|
|
1336
1470
|
constructor(config) {
|
|
1337
1471
|
this.name = config.name;
|
|
1338
1472
|
this.description = config.description;
|
|
@@ -1342,254 +1476,134 @@ var ManagedTool = class {
|
|
|
1342
1476
|
this.healthCheckFn = config.healthCheck?.bind(this);
|
|
1343
1477
|
this.autoCleanup = config.autoCleanup ?? true;
|
|
1344
1478
|
this.healthCheckInterval = config.healthCheckInterval;
|
|
1345
|
-
this.
|
|
1479
|
+
this.state = {
|
|
1480
|
+
initialized: false,
|
|
1481
|
+
context: config.context,
|
|
1482
|
+
stats: {
|
|
1483
|
+
initialized: false,
|
|
1484
|
+
totalExecutions: 0,
|
|
1485
|
+
successfulExecutions: 0,
|
|
1486
|
+
failedExecutions: 0
|
|
1487
|
+
},
|
|
1488
|
+
healthCheckInFlight: false,
|
|
1489
|
+
cleaningUp: false,
|
|
1490
|
+
lifecycleGeneration: 0
|
|
1491
|
+
};
|
|
1346
1492
|
this.ensureBeforeExitHandler();
|
|
1347
1493
|
}
|
|
1348
|
-
/**
|
|
1349
|
-
* Get the tool context (e.g., connection pool, API client)
|
|
1350
|
-
*/
|
|
1351
1494
|
get context() {
|
|
1352
|
-
return this.
|
|
1495
|
+
return this.state.context;
|
|
1353
1496
|
}
|
|
1354
|
-
/**
|
|
1355
|
-
* Set the tool context
|
|
1356
|
-
*/
|
|
1357
1497
|
set context(value) {
|
|
1358
|
-
this.
|
|
1498
|
+
this.state.context = value;
|
|
1359
1499
|
}
|
|
1360
|
-
/**
|
|
1361
|
-
* Check if tool is initialized
|
|
1362
|
-
*/
|
|
1363
1500
|
get initialized() {
|
|
1364
|
-
return this.
|
|
1501
|
+
return this.state.initialized;
|
|
1365
1502
|
}
|
|
1366
|
-
/**
|
|
1367
|
-
* Initialize the tool
|
|
1368
|
-
*/
|
|
1369
1503
|
async initialize() {
|
|
1370
|
-
if (this.
|
|
1371
|
-
await this.
|
|
1504
|
+
if (this.state.initializePromise) {
|
|
1505
|
+
await this.state.initializePromise;
|
|
1372
1506
|
return;
|
|
1373
1507
|
}
|
|
1374
|
-
if (this.
|
|
1375
|
-
await this.
|
|
1376
|
-
if (this.
|
|
1377
|
-
await this.
|
|
1508
|
+
if (this.state.cleanupPromise) {
|
|
1509
|
+
await this.state.cleanupPromise;
|
|
1510
|
+
if (this.state.initializePromise) {
|
|
1511
|
+
await this.state.initializePromise;
|
|
1378
1512
|
return;
|
|
1379
1513
|
}
|
|
1380
1514
|
}
|
|
1381
|
-
if (this.
|
|
1515
|
+
if (this.state.initialized) {
|
|
1382
1516
|
return;
|
|
1383
1517
|
}
|
|
1384
|
-
const initializePromise =
|
|
1385
|
-
|
|
1518
|
+
const initializePromise = performManagedInitialize({
|
|
1519
|
+
ensureBeforeExitHandler: () => this.ensureBeforeExitHandler(),
|
|
1520
|
+
healthCheckFn: this.healthCheckFn,
|
|
1521
|
+
healthCheckInterval: this.healthCheckInterval,
|
|
1522
|
+
initializeFn: this.initializeFn,
|
|
1523
|
+
runPeriodicHealthCheck: () => this.runPeriodicHealthCheck(),
|
|
1524
|
+
state: this.state
|
|
1525
|
+
});
|
|
1526
|
+
this.state.initializePromise = initializePromise;
|
|
1386
1527
|
try {
|
|
1387
1528
|
await initializePromise;
|
|
1388
1529
|
} finally {
|
|
1389
|
-
this.
|
|
1530
|
+
this.state.initializePromise = void 0;
|
|
1390
1531
|
}
|
|
1391
1532
|
}
|
|
1392
|
-
/**
|
|
1393
|
-
* Execute the tool
|
|
1394
|
-
*/
|
|
1395
1533
|
async execute(input) {
|
|
1396
|
-
if (!this.
|
|
1534
|
+
if (!this.state.initialized) {
|
|
1397
1535
|
throw new Error(`Tool ${this.name} is not initialized. Call initialize() first.`);
|
|
1398
1536
|
}
|
|
1399
1537
|
const startTime = Date.now();
|
|
1400
|
-
this.
|
|
1538
|
+
this.state.stats.totalExecutions++;
|
|
1401
1539
|
try {
|
|
1402
1540
|
const result = await this.executeFn(input);
|
|
1403
|
-
this.
|
|
1404
|
-
this.
|
|
1541
|
+
this.state.stats.successfulExecutions++;
|
|
1542
|
+
this.state.stats.lastExecutionTime = Date.now() - startTime;
|
|
1405
1543
|
return result;
|
|
1406
1544
|
} catch (error) {
|
|
1407
|
-
this.
|
|
1408
|
-
this.
|
|
1545
|
+
this.state.stats.failedExecutions++;
|
|
1546
|
+
this.state.stats.lastExecutionTime = Date.now() - startTime;
|
|
1409
1547
|
throw error;
|
|
1410
1548
|
}
|
|
1411
1549
|
}
|
|
1412
|
-
/**
|
|
1413
|
-
* Cleanup the tool
|
|
1414
|
-
*/
|
|
1415
1550
|
async cleanup() {
|
|
1416
|
-
if (this.
|
|
1417
|
-
await this.
|
|
1551
|
+
if (this.state.cleanupPromise) {
|
|
1552
|
+
await this.state.cleanupPromise;
|
|
1418
1553
|
return;
|
|
1419
1554
|
}
|
|
1420
|
-
if (this.
|
|
1555
|
+
if (this.state.initializePromise) {
|
|
1421
1556
|
try {
|
|
1422
|
-
await this.
|
|
1557
|
+
await this.state.initializePromise;
|
|
1423
1558
|
} catch {
|
|
1424
1559
|
}
|
|
1425
1560
|
}
|
|
1426
|
-
const cleanupPromise =
|
|
1427
|
-
|
|
1561
|
+
const cleanupPromise = performManagedCleanup({
|
|
1562
|
+
cleanupFn: this.cleanupFn,
|
|
1563
|
+
state: this.state
|
|
1564
|
+
});
|
|
1565
|
+
this.state.cleanupPromise = cleanupPromise;
|
|
1428
1566
|
try {
|
|
1429
1567
|
await cleanupPromise;
|
|
1430
1568
|
} finally {
|
|
1431
|
-
this.
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
async performCleanup() {
|
|
1435
|
-
this._cleaningUp = true;
|
|
1436
|
-
if (this._healthCheckTimer) {
|
|
1437
|
-
clearInterval(this._healthCheckTimer);
|
|
1438
|
-
this._healthCheckTimer = void 0;
|
|
1439
|
-
}
|
|
1440
|
-
if (this._beforeExitHandler) {
|
|
1441
|
-
process.off("beforeExit", this._beforeExitHandler);
|
|
1442
|
-
this._beforeExitHandler = void 0;
|
|
1443
|
-
}
|
|
1444
|
-
if (!this._initialized) {
|
|
1445
|
-
this._cleaningUp = false;
|
|
1446
|
-
return;
|
|
1569
|
+
this.state.cleanupPromise = void 0;
|
|
1447
1570
|
}
|
|
1448
|
-
this._initialized = false;
|
|
1449
|
-
this._stats.initialized = false;
|
|
1450
|
-
if (this.cleanupFn) {
|
|
1451
|
-
try {
|
|
1452
|
-
await this.cleanupFn();
|
|
1453
|
-
} finally {
|
|
1454
|
-
this._cleaningUp = false;
|
|
1455
|
-
}
|
|
1456
|
-
return;
|
|
1457
|
-
}
|
|
1458
|
-
this._cleaningUp = false;
|
|
1459
1571
|
}
|
|
1460
|
-
/**
|
|
1461
|
-
* Run health check
|
|
1462
|
-
*/
|
|
1463
1572
|
async healthCheck() {
|
|
1464
|
-
|
|
1465
|
-
return {
|
|
1466
|
-
healthy: false,
|
|
1467
|
-
error: "Tool is not initialized"
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
|
-
if (!this.healthCheckFn) {
|
|
1471
|
-
return {
|
|
1472
|
-
healthy: true,
|
|
1473
|
-
metadata: { message: "No health check configured" }
|
|
1474
|
-
};
|
|
1475
|
-
}
|
|
1476
|
-
const lifecycleGeneration = this._lifecycleGeneration;
|
|
1477
|
-
try {
|
|
1478
|
-
const result = await this.healthCheckFn();
|
|
1479
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1480
|
-
return {
|
|
1481
|
-
healthy: false,
|
|
1482
|
-
error: "Tool is not initialized"
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
this._stats.lastHealthCheck = result;
|
|
1486
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1487
|
-
return result;
|
|
1488
|
-
} catch (error) {
|
|
1489
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1490
|
-
return {
|
|
1491
|
-
healthy: false,
|
|
1492
|
-
error: "Tool is not initialized"
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
const result = {
|
|
1496
|
-
healthy: false,
|
|
1497
|
-
error: getErrorMessage(error)
|
|
1498
|
-
};
|
|
1499
|
-
this._stats.lastHealthCheck = result;
|
|
1500
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1501
|
-
return result;
|
|
1502
|
-
}
|
|
1573
|
+
return runManagedHealthCheck(this.state, this.healthCheckFn);
|
|
1503
1574
|
}
|
|
1504
|
-
/**
|
|
1505
|
-
* Get tool statistics
|
|
1506
|
-
*/
|
|
1507
1575
|
getStats() {
|
|
1508
|
-
return { ...this.
|
|
1576
|
+
return { ...this.state.stats };
|
|
1509
1577
|
}
|
|
1510
|
-
/**
|
|
1511
|
-
* Reset statistics
|
|
1512
|
-
*/
|
|
1513
1578
|
resetStats() {
|
|
1514
|
-
this.
|
|
1515
|
-
this.
|
|
1516
|
-
this.
|
|
1517
|
-
this.
|
|
1579
|
+
this.state.stats.totalExecutions = 0;
|
|
1580
|
+
this.state.stats.successfulExecutions = 0;
|
|
1581
|
+
this.state.stats.failedExecutions = 0;
|
|
1582
|
+
this.state.stats.lastExecutionTime = void 0;
|
|
1518
1583
|
}
|
|
1519
|
-
/**
|
|
1520
|
-
* Convert to LangChain tool format
|
|
1521
|
-
*/
|
|
1522
1584
|
toLangChainTool() {
|
|
1523
1585
|
return {
|
|
1524
1586
|
name: this.name,
|
|
1525
1587
|
description: this.description,
|
|
1526
|
-
invoke: async (input) =>
|
|
1527
|
-
return await this.execute(input);
|
|
1528
|
-
}
|
|
1588
|
+
invoke: async (input) => this.execute(input)
|
|
1529
1589
|
};
|
|
1530
1590
|
}
|
|
1531
1591
|
async runPeriodicHealthCheck() {
|
|
1532
|
-
|
|
1533
|
-
return;
|
|
1534
|
-
}
|
|
1535
|
-
this._healthCheckInFlight = true;
|
|
1536
|
-
const lifecycleGeneration = this._lifecycleGeneration;
|
|
1537
|
-
try {
|
|
1538
|
-
const result = await this.healthCheckFn();
|
|
1539
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
this._stats.lastHealthCheck = result;
|
|
1543
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1544
|
-
} catch (error) {
|
|
1545
|
-
if (!this._initialized || this._cleaningUp || this._lifecycleGeneration !== lifecycleGeneration) {
|
|
1546
|
-
return;
|
|
1547
|
-
}
|
|
1548
|
-
this._stats.lastHealthCheck = {
|
|
1549
|
-
healthy: false,
|
|
1550
|
-
error: getErrorMessage(error)
|
|
1551
|
-
};
|
|
1552
|
-
this._stats.lastHealthCheckTime = Date.now();
|
|
1553
|
-
} finally {
|
|
1554
|
-
this._healthCheckInFlight = false;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
async performInitialize() {
|
|
1558
|
-
this.ensureBeforeExitHandler();
|
|
1559
|
-
this._lifecycleGeneration++;
|
|
1560
|
-
if (this.initializeFn) {
|
|
1561
|
-
await this.initializeFn();
|
|
1562
|
-
}
|
|
1563
|
-
this._initialized = true;
|
|
1564
|
-
this._stats.initialized = true;
|
|
1565
|
-
if (this.healthCheckInterval && this.healthCheckFn) {
|
|
1566
|
-
this._healthCheckTimer = setInterval(() => {
|
|
1567
|
-
void this.runPeriodicHealthCheck();
|
|
1568
|
-
}, this.healthCheckInterval);
|
|
1569
|
-
}
|
|
1592
|
+
await runPeriodicManagedHealthCheck(this.state, this.healthCheckFn);
|
|
1570
1593
|
}
|
|
1571
1594
|
ensureBeforeExitHandler() {
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
this.
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
error: getErrorMessage(err),
|
|
1580
|
-
...err instanceof Error && err.stack ? { stack: err.stack } : {}
|
|
1581
|
-
})
|
|
1582
|
-
);
|
|
1583
|
-
};
|
|
1584
|
-
process.on("beforeExit", this._beforeExitHandler);
|
|
1595
|
+
ensureManagedBeforeExitHandler({
|
|
1596
|
+
autoCleanup: this.autoCleanup,
|
|
1597
|
+
cleanup: () => this.cleanup(),
|
|
1598
|
+
logger: logger3,
|
|
1599
|
+
name: this.name,
|
|
1600
|
+
state: this.state
|
|
1601
|
+
});
|
|
1585
1602
|
}
|
|
1586
1603
|
};
|
|
1587
1604
|
function createManagedTool(config) {
|
|
1588
1605
|
return new ManagedTool(config);
|
|
1589
1606
|
}
|
|
1590
|
-
function getErrorMessage(error) {
|
|
1591
|
-
return error instanceof Error ? error.message : String(error);
|
|
1592
|
-
}
|
|
1593
1607
|
|
|
1594
1608
|
// src/tools/composition.ts
|
|
1595
1609
|
function isConditionalStep(step) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentforge/core",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.45",
|
|
4
4
|
"description": "Production-ready TypeScript agent framework built on LangGraph with orchestration, middleware, and typed abstractions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|