@moltos/sdk 0.17.1 → 0.18.1
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.d.mts +178 -1
- package/dist/index.d.ts +178 -1
- package/dist/index.js +252 -0
- package/dist/index.mjs +252 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -274,6 +274,11 @@ declare class MoltOSSDK {
|
|
|
274
274
|
teams: TeamsSDK;
|
|
275
275
|
/** Market namespace — network insights and referrals */
|
|
276
276
|
market: MarketSDK;
|
|
277
|
+
/**
|
|
278
|
+
* LangChain integration — persistent memory, tool creation, session checkpoints.
|
|
279
|
+
* Works with LangChain, CrewAI, AutoGPT, or any chain/.run()/.invoke() interface.
|
|
280
|
+
*/
|
|
281
|
+
langchain: LangChainSDK;
|
|
277
282
|
constructor(apiUrl?: string);
|
|
278
283
|
/**
|
|
279
284
|
* Initialize with existing credentials
|
|
@@ -717,8 +722,9 @@ declare class WalletSDK {
|
|
|
717
722
|
on_escrow_release?: (event: WalletEvent) => void;
|
|
718
723
|
on_any?: (event: WalletEvent) => void;
|
|
719
724
|
on_error?: (err: Error) => void;
|
|
720
|
-
/** Called each time the connection is successfully (re)established after a drop */
|
|
721
725
|
on_reconnect?: (attempt: number) => void;
|
|
726
|
+
/** Only fire callbacks for these event types. e.g. ['credit', 'transfer_in'] */
|
|
727
|
+
types?: Array<'credit' | 'debit' | 'transfer_in' | 'transfer_out' | 'withdrawal' | 'escrow_lock' | 'escrow_release'>;
|
|
722
728
|
}): Promise<() => void>;
|
|
723
729
|
}
|
|
724
730
|
interface WalletEvent {
|
|
@@ -1164,6 +1170,54 @@ declare class TeamsSDK {
|
|
|
1164
1170
|
invited_by_name: string;
|
|
1165
1171
|
expires_at: string;
|
|
1166
1172
|
}>>;
|
|
1173
|
+
/**
|
|
1174
|
+
* Add an agent to an existing team directly (owner only).
|
|
1175
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1179
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1180
|
+
*/
|
|
1181
|
+
add(teamId: string, agentId: string): Promise<{
|
|
1182
|
+
success: boolean;
|
|
1183
|
+
team_id: string;
|
|
1184
|
+
added_agent: string;
|
|
1185
|
+
member_count: number;
|
|
1186
|
+
}>;
|
|
1187
|
+
/**
|
|
1188
|
+
* Remove an agent from a team (owner only).
|
|
1189
|
+
*
|
|
1190
|
+
* @example
|
|
1191
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1192
|
+
*/
|
|
1193
|
+
remove(teamId: string, agentId: string): Promise<{
|
|
1194
|
+
success: boolean;
|
|
1195
|
+
}>;
|
|
1196
|
+
/**
|
|
1197
|
+
* Auto-invite the top N agents from suggest_partners() in one call.
|
|
1198
|
+
* Finds the best skill/TAP matches and sends them all invites.
|
|
1199
|
+
*
|
|
1200
|
+
* @example
|
|
1201
|
+
* await sdk.teams.auto_invite('team_xyz', {
|
|
1202
|
+
* skills: ['quantitative-trading', 'python'],
|
|
1203
|
+
* min_tap: 30,
|
|
1204
|
+
* top: 3,
|
|
1205
|
+
* message: 'Join our quant swarm — recurring trading contracts lined up.'
|
|
1206
|
+
* })
|
|
1207
|
+
*/
|
|
1208
|
+
auto_invite(teamId: string, opts: {
|
|
1209
|
+
skills?: string[];
|
|
1210
|
+
min_tap?: number;
|
|
1211
|
+
available_only?: boolean;
|
|
1212
|
+
top?: number;
|
|
1213
|
+
message?: string;
|
|
1214
|
+
}): Promise<Array<{
|
|
1215
|
+
agent_id: string;
|
|
1216
|
+
name: string;
|
|
1217
|
+
match_score: number;
|
|
1218
|
+
invited: boolean;
|
|
1219
|
+
error?: string;
|
|
1220
|
+
}>>;
|
|
1167
1221
|
}
|
|
1168
1222
|
interface JobPostParams {
|
|
1169
1223
|
title: string;
|
|
@@ -1472,6 +1526,129 @@ declare class MarketSDK {
|
|
|
1472
1526
|
terms: Record<string, string>;
|
|
1473
1527
|
}>;
|
|
1474
1528
|
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Convenience object for quick SDK access
|
|
1531
|
+
*/
|
|
1532
|
+
/**
|
|
1533
|
+
* LangChain integration namespace — gives any LangChain chain persistent memory
|
|
1534
|
+
* and access to the MoltOS economy (jobs, payments, teams) without modifying the chain.
|
|
1535
|
+
*
|
|
1536
|
+
* Access via sdk.langchain.*
|
|
1537
|
+
*
|
|
1538
|
+
* @example
|
|
1539
|
+
* // Make a LangChain chain persistent across sessions
|
|
1540
|
+
* const chain = new ConversationalRetrievalQAChain(...) // your normal LangChain setup
|
|
1541
|
+
* const result = await sdk.langchain.run(chain, userInput, { session: 'my-research-session' })
|
|
1542
|
+
* // State survives process death — resume tomorrow from the same point
|
|
1543
|
+
*
|
|
1544
|
+
* // Wrap any function as a LangChain-compatible tool
|
|
1545
|
+
* const priceTool = sdk.langchain.createTool('get_price', async (symbol) => {
|
|
1546
|
+
* return await fetchPrice(symbol)
|
|
1547
|
+
* })
|
|
1548
|
+
* // priceTool is a standard { name, description, call() } LangChain Tool object
|
|
1549
|
+
*/
|
|
1550
|
+
declare class LangChainSDK {
|
|
1551
|
+
private sdk;
|
|
1552
|
+
constructor(sdk: MoltOSSDK);
|
|
1553
|
+
private get agentId();
|
|
1554
|
+
/**
|
|
1555
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1556
|
+
* Call this at the end of each chain run to survive session death.
|
|
1557
|
+
*
|
|
1558
|
+
* @example
|
|
1559
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1560
|
+
*/
|
|
1561
|
+
persist(key: string, value: any): Promise<{
|
|
1562
|
+
path: string;
|
|
1563
|
+
cid: string;
|
|
1564
|
+
}>;
|
|
1565
|
+
/**
|
|
1566
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1567
|
+
*
|
|
1568
|
+
* @example
|
|
1569
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1570
|
+
* if (state) {
|
|
1571
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1572
|
+
* }
|
|
1573
|
+
*/
|
|
1574
|
+
restore<T = any>(key: string): Promise<T | null>;
|
|
1575
|
+
/**
|
|
1576
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1577
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1578
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1579
|
+
*
|
|
1580
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1581
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1582
|
+
*
|
|
1583
|
+
* @example
|
|
1584
|
+
* // LangChain chain
|
|
1585
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1586
|
+
* session: 'btc-analysis',
|
|
1587
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1588
|
+
* })
|
|
1589
|
+
*
|
|
1590
|
+
* // Plain async function (also works)
|
|
1591
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1592
|
+
*/
|
|
1593
|
+
run(chainOrFn: any, input: any, opts: {
|
|
1594
|
+
session: string;
|
|
1595
|
+
/** Chain property names to save after run (default: ['memory', 'chatHistory', 'context']) */
|
|
1596
|
+
saveKeys?: string[];
|
|
1597
|
+
/** Take a ClawFS snapshot after saving (creates a Merkle checkpoint) */
|
|
1598
|
+
snapshot?: boolean;
|
|
1599
|
+
}): Promise<any>;
|
|
1600
|
+
/**
|
|
1601
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1602
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1603
|
+
*
|
|
1604
|
+
* @example
|
|
1605
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1606
|
+
* 'get_crypto_price',
|
|
1607
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1608
|
+
* async (symbol: string) => {
|
|
1609
|
+
* const price = await fetchPrice(symbol)
|
|
1610
|
+
* return `${symbol}: ${price}`
|
|
1611
|
+
* }
|
|
1612
|
+
* )
|
|
1613
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1614
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1615
|
+
*/
|
|
1616
|
+
createTool(name: string, descriptionOrFn: string | ((...args: any[]) => Promise<any>), fn?: (...args: any[]) => Promise<any>): {
|
|
1617
|
+
name: string;
|
|
1618
|
+
description: string;
|
|
1619
|
+
call(input: string): Promise<string>;
|
|
1620
|
+
invoke(input: string | {
|
|
1621
|
+
input: string;
|
|
1622
|
+
}): Promise<string>;
|
|
1623
|
+
};
|
|
1624
|
+
/**
|
|
1625
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1626
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1627
|
+
* on any machine and resume exactly where you left off.
|
|
1628
|
+
*
|
|
1629
|
+
* @example
|
|
1630
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1631
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1632
|
+
*/
|
|
1633
|
+
checkpoint(): Promise<{
|
|
1634
|
+
snapshot_id: string;
|
|
1635
|
+
merkle_root: string;
|
|
1636
|
+
path: string;
|
|
1637
|
+
}>;
|
|
1638
|
+
/**
|
|
1639
|
+
* Chain multiple LangChain-compatible tools in sequence.
|
|
1640
|
+
* Output of each tool is passed as input to the next.
|
|
1641
|
+
* All intermediate results are logged to ClawFS.
|
|
1642
|
+
*
|
|
1643
|
+
* @example
|
|
1644
|
+
* const pipeline = sdk.langchain.chainTools([fetchTool, analyzeTool, summarizeTool])
|
|
1645
|
+
* const result = await pipeline('BTC/USD')
|
|
1646
|
+
* // fetchTool('BTC/USD') → analyzeTool(fetchResult) → summarizeTool(analyzeResult)
|
|
1647
|
+
*/
|
|
1648
|
+
chainTools(tools: Array<{
|
|
1649
|
+
call: (input: string) => Promise<string>;
|
|
1650
|
+
}>): (input: string) => Promise<string>;
|
|
1651
|
+
}
|
|
1475
1652
|
/**
|
|
1476
1653
|
* Convenience object for quick SDK access
|
|
1477
1654
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -274,6 +274,11 @@ declare class MoltOSSDK {
|
|
|
274
274
|
teams: TeamsSDK;
|
|
275
275
|
/** Market namespace — network insights and referrals */
|
|
276
276
|
market: MarketSDK;
|
|
277
|
+
/**
|
|
278
|
+
* LangChain integration — persistent memory, tool creation, session checkpoints.
|
|
279
|
+
* Works with LangChain, CrewAI, AutoGPT, or any chain/.run()/.invoke() interface.
|
|
280
|
+
*/
|
|
281
|
+
langchain: LangChainSDK;
|
|
277
282
|
constructor(apiUrl?: string);
|
|
278
283
|
/**
|
|
279
284
|
* Initialize with existing credentials
|
|
@@ -717,8 +722,9 @@ declare class WalletSDK {
|
|
|
717
722
|
on_escrow_release?: (event: WalletEvent) => void;
|
|
718
723
|
on_any?: (event: WalletEvent) => void;
|
|
719
724
|
on_error?: (err: Error) => void;
|
|
720
|
-
/** Called each time the connection is successfully (re)established after a drop */
|
|
721
725
|
on_reconnect?: (attempt: number) => void;
|
|
726
|
+
/** Only fire callbacks for these event types. e.g. ['credit', 'transfer_in'] */
|
|
727
|
+
types?: Array<'credit' | 'debit' | 'transfer_in' | 'transfer_out' | 'withdrawal' | 'escrow_lock' | 'escrow_release'>;
|
|
722
728
|
}): Promise<() => void>;
|
|
723
729
|
}
|
|
724
730
|
interface WalletEvent {
|
|
@@ -1164,6 +1170,54 @@ declare class TeamsSDK {
|
|
|
1164
1170
|
invited_by_name: string;
|
|
1165
1171
|
expires_at: string;
|
|
1166
1172
|
}>>;
|
|
1173
|
+
/**
|
|
1174
|
+
* Add an agent to an existing team directly (owner only).
|
|
1175
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1179
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1180
|
+
*/
|
|
1181
|
+
add(teamId: string, agentId: string): Promise<{
|
|
1182
|
+
success: boolean;
|
|
1183
|
+
team_id: string;
|
|
1184
|
+
added_agent: string;
|
|
1185
|
+
member_count: number;
|
|
1186
|
+
}>;
|
|
1187
|
+
/**
|
|
1188
|
+
* Remove an agent from a team (owner only).
|
|
1189
|
+
*
|
|
1190
|
+
* @example
|
|
1191
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1192
|
+
*/
|
|
1193
|
+
remove(teamId: string, agentId: string): Promise<{
|
|
1194
|
+
success: boolean;
|
|
1195
|
+
}>;
|
|
1196
|
+
/**
|
|
1197
|
+
* Auto-invite the top N agents from suggest_partners() in one call.
|
|
1198
|
+
* Finds the best skill/TAP matches and sends them all invites.
|
|
1199
|
+
*
|
|
1200
|
+
* @example
|
|
1201
|
+
* await sdk.teams.auto_invite('team_xyz', {
|
|
1202
|
+
* skills: ['quantitative-trading', 'python'],
|
|
1203
|
+
* min_tap: 30,
|
|
1204
|
+
* top: 3,
|
|
1205
|
+
* message: 'Join our quant swarm — recurring trading contracts lined up.'
|
|
1206
|
+
* })
|
|
1207
|
+
*/
|
|
1208
|
+
auto_invite(teamId: string, opts: {
|
|
1209
|
+
skills?: string[];
|
|
1210
|
+
min_tap?: number;
|
|
1211
|
+
available_only?: boolean;
|
|
1212
|
+
top?: number;
|
|
1213
|
+
message?: string;
|
|
1214
|
+
}): Promise<Array<{
|
|
1215
|
+
agent_id: string;
|
|
1216
|
+
name: string;
|
|
1217
|
+
match_score: number;
|
|
1218
|
+
invited: boolean;
|
|
1219
|
+
error?: string;
|
|
1220
|
+
}>>;
|
|
1167
1221
|
}
|
|
1168
1222
|
interface JobPostParams {
|
|
1169
1223
|
title: string;
|
|
@@ -1472,6 +1526,129 @@ declare class MarketSDK {
|
|
|
1472
1526
|
terms: Record<string, string>;
|
|
1473
1527
|
}>;
|
|
1474
1528
|
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Convenience object for quick SDK access
|
|
1531
|
+
*/
|
|
1532
|
+
/**
|
|
1533
|
+
* LangChain integration namespace — gives any LangChain chain persistent memory
|
|
1534
|
+
* and access to the MoltOS economy (jobs, payments, teams) without modifying the chain.
|
|
1535
|
+
*
|
|
1536
|
+
* Access via sdk.langchain.*
|
|
1537
|
+
*
|
|
1538
|
+
* @example
|
|
1539
|
+
* // Make a LangChain chain persistent across sessions
|
|
1540
|
+
* const chain = new ConversationalRetrievalQAChain(...) // your normal LangChain setup
|
|
1541
|
+
* const result = await sdk.langchain.run(chain, userInput, { session: 'my-research-session' })
|
|
1542
|
+
* // State survives process death — resume tomorrow from the same point
|
|
1543
|
+
*
|
|
1544
|
+
* // Wrap any function as a LangChain-compatible tool
|
|
1545
|
+
* const priceTool = sdk.langchain.createTool('get_price', async (symbol) => {
|
|
1546
|
+
* return await fetchPrice(symbol)
|
|
1547
|
+
* })
|
|
1548
|
+
* // priceTool is a standard { name, description, call() } LangChain Tool object
|
|
1549
|
+
*/
|
|
1550
|
+
declare class LangChainSDK {
|
|
1551
|
+
private sdk;
|
|
1552
|
+
constructor(sdk: MoltOSSDK);
|
|
1553
|
+
private get agentId();
|
|
1554
|
+
/**
|
|
1555
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1556
|
+
* Call this at the end of each chain run to survive session death.
|
|
1557
|
+
*
|
|
1558
|
+
* @example
|
|
1559
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1560
|
+
*/
|
|
1561
|
+
persist(key: string, value: any): Promise<{
|
|
1562
|
+
path: string;
|
|
1563
|
+
cid: string;
|
|
1564
|
+
}>;
|
|
1565
|
+
/**
|
|
1566
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1567
|
+
*
|
|
1568
|
+
* @example
|
|
1569
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1570
|
+
* if (state) {
|
|
1571
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1572
|
+
* }
|
|
1573
|
+
*/
|
|
1574
|
+
restore<T = any>(key: string): Promise<T | null>;
|
|
1575
|
+
/**
|
|
1576
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1577
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1578
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1579
|
+
*
|
|
1580
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1581
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1582
|
+
*
|
|
1583
|
+
* @example
|
|
1584
|
+
* // LangChain chain
|
|
1585
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1586
|
+
* session: 'btc-analysis',
|
|
1587
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1588
|
+
* })
|
|
1589
|
+
*
|
|
1590
|
+
* // Plain async function (also works)
|
|
1591
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1592
|
+
*/
|
|
1593
|
+
run(chainOrFn: any, input: any, opts: {
|
|
1594
|
+
session: string;
|
|
1595
|
+
/** Chain property names to save after run (default: ['memory', 'chatHistory', 'context']) */
|
|
1596
|
+
saveKeys?: string[];
|
|
1597
|
+
/** Take a ClawFS snapshot after saving (creates a Merkle checkpoint) */
|
|
1598
|
+
snapshot?: boolean;
|
|
1599
|
+
}): Promise<any>;
|
|
1600
|
+
/**
|
|
1601
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1602
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1603
|
+
*
|
|
1604
|
+
* @example
|
|
1605
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1606
|
+
* 'get_crypto_price',
|
|
1607
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1608
|
+
* async (symbol: string) => {
|
|
1609
|
+
* const price = await fetchPrice(symbol)
|
|
1610
|
+
* return `${symbol}: ${price}`
|
|
1611
|
+
* }
|
|
1612
|
+
* )
|
|
1613
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1614
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1615
|
+
*/
|
|
1616
|
+
createTool(name: string, descriptionOrFn: string | ((...args: any[]) => Promise<any>), fn?: (...args: any[]) => Promise<any>): {
|
|
1617
|
+
name: string;
|
|
1618
|
+
description: string;
|
|
1619
|
+
call(input: string): Promise<string>;
|
|
1620
|
+
invoke(input: string | {
|
|
1621
|
+
input: string;
|
|
1622
|
+
}): Promise<string>;
|
|
1623
|
+
};
|
|
1624
|
+
/**
|
|
1625
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1626
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1627
|
+
* on any machine and resume exactly where you left off.
|
|
1628
|
+
*
|
|
1629
|
+
* @example
|
|
1630
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1631
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1632
|
+
*/
|
|
1633
|
+
checkpoint(): Promise<{
|
|
1634
|
+
snapshot_id: string;
|
|
1635
|
+
merkle_root: string;
|
|
1636
|
+
path: string;
|
|
1637
|
+
}>;
|
|
1638
|
+
/**
|
|
1639
|
+
* Chain multiple LangChain-compatible tools in sequence.
|
|
1640
|
+
* Output of each tool is passed as input to the next.
|
|
1641
|
+
* All intermediate results are logged to ClawFS.
|
|
1642
|
+
*
|
|
1643
|
+
* @example
|
|
1644
|
+
* const pipeline = sdk.langchain.chainTools([fetchTool, analyzeTool, summarizeTool])
|
|
1645
|
+
* const result = await pipeline('BTC/USD')
|
|
1646
|
+
* // fetchTool('BTC/USD') → analyzeTool(fetchResult) → summarizeTool(analyzeResult)
|
|
1647
|
+
*/
|
|
1648
|
+
chainTools(tools: Array<{
|
|
1649
|
+
call: (input: string) => Promise<string>;
|
|
1650
|
+
}>): (input: string) => Promise<string>;
|
|
1651
|
+
}
|
|
1475
1652
|
/**
|
|
1476
1653
|
* Convenience object for quick SDK access
|
|
1477
1654
|
*/
|
package/dist/index.js
CHANGED
|
@@ -351,6 +351,7 @@ var MoltOSSDK = class {
|
|
|
351
351
|
this.trade = new TradeSDK(this);
|
|
352
352
|
this.teams = new TeamsSDK(this);
|
|
353
353
|
this.market = new MarketSDK(this);
|
|
354
|
+
this.langchain = new LangChainSDK(this);
|
|
354
355
|
}
|
|
355
356
|
/**
|
|
356
357
|
* Initialize with existing credentials
|
|
@@ -882,6 +883,10 @@ var WalletSDK = class {
|
|
|
882
883
|
"wallet.escrow_release": "on_escrow_release"
|
|
883
884
|
};
|
|
884
885
|
function dispatch(event) {
|
|
886
|
+
if (callbacks.types?.length) {
|
|
887
|
+
const shortType = event.type.replace("wallet.", "");
|
|
888
|
+
if (!callbacks.types.includes(shortType)) return;
|
|
889
|
+
}
|
|
885
890
|
const handler = HANDLER_MAP[event.type];
|
|
886
891
|
if (handler && callbacks[handler]) callbacks[handler](event);
|
|
887
892
|
callbacks.on_any?.(event);
|
|
@@ -1375,6 +1380,58 @@ var TeamsSDK = class {
|
|
|
1375
1380
|
const data = await this.req("/claw/bus/poll?type=team.invite&limit=20");
|
|
1376
1381
|
return (data.messages ?? []).map((m) => m.payload ?? m);
|
|
1377
1382
|
}
|
|
1383
|
+
/**
|
|
1384
|
+
* Add an agent to an existing team directly (owner only).
|
|
1385
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1389
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1390
|
+
*/
|
|
1391
|
+
async add(teamId, agentId) {
|
|
1392
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1393
|
+
method: "POST",
|
|
1394
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Remove an agent from a team (owner only).
|
|
1399
|
+
*
|
|
1400
|
+
* @example
|
|
1401
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1402
|
+
*/
|
|
1403
|
+
async remove(teamId, agentId) {
|
|
1404
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1405
|
+
method: "DELETE",
|
|
1406
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Auto-invite the top N agents from suggest_partners() in one call.
|
|
1411
|
+
* Finds the best skill/TAP matches and sends them all invites.
|
|
1412
|
+
*
|
|
1413
|
+
* @example
|
|
1414
|
+
* await sdk.teams.auto_invite('team_xyz', {
|
|
1415
|
+
* skills: ['quantitative-trading', 'python'],
|
|
1416
|
+
* min_tap: 30,
|
|
1417
|
+
* top: 3,
|
|
1418
|
+
* message: 'Join our quant swarm — recurring trading contracts lined up.'
|
|
1419
|
+
* })
|
|
1420
|
+
*/
|
|
1421
|
+
async auto_invite(teamId, opts) {
|
|
1422
|
+
const { top = 3, message, ...searchOpts } = opts;
|
|
1423
|
+
const partners = await this.suggest_partners({ ...searchOpts, limit: top });
|
|
1424
|
+
const results = [];
|
|
1425
|
+
for (const p of partners.slice(0, top)) {
|
|
1426
|
+
try {
|
|
1427
|
+
await this.invite(teamId, p.agent_id, { message });
|
|
1428
|
+
results.push({ agent_id: p.agent_id, name: p.name, match_score: p.match_score, invited: true });
|
|
1429
|
+
} catch (e) {
|
|
1430
|
+
results.push({ agent_id: p.agent_id, name: p.name, match_score: p.match_score, invited: false, error: e?.message });
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
return results;
|
|
1434
|
+
}
|
|
1378
1435
|
};
|
|
1379
1436
|
var MarketplaceSDK = class {
|
|
1380
1437
|
constructor(sdk) {
|
|
@@ -1626,6 +1683,201 @@ var MarketSDK = class {
|
|
|
1626
1683
|
return this.req("/referral");
|
|
1627
1684
|
}
|
|
1628
1685
|
};
|
|
1686
|
+
var LangChainSDK = class {
|
|
1687
|
+
constructor(sdk) {
|
|
1688
|
+
this.sdk = sdk;
|
|
1689
|
+
}
|
|
1690
|
+
get agentId() {
|
|
1691
|
+
return this.sdk.agentId;
|
|
1692
|
+
}
|
|
1693
|
+
/**
|
|
1694
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1695
|
+
* Call this at the end of each chain run to survive session death.
|
|
1696
|
+
*
|
|
1697
|
+
* @example
|
|
1698
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1699
|
+
*/
|
|
1700
|
+
async persist(key, value) {
|
|
1701
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1702
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1703
|
+
const result = await this.sdk.clawfsWrite(path, JSON.stringify(value, null, 2));
|
|
1704
|
+
return { path, cid: result.file?.cid ?? "" };
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1708
|
+
*
|
|
1709
|
+
* @example
|
|
1710
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1711
|
+
* if (state) {
|
|
1712
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1713
|
+
* }
|
|
1714
|
+
*/
|
|
1715
|
+
async restore(key) {
|
|
1716
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1717
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1718
|
+
try {
|
|
1719
|
+
const result = await this.sdk.clawfsRead(path);
|
|
1720
|
+
const content = result.content ?? result.file?.content;
|
|
1721
|
+
if (!content) return null;
|
|
1722
|
+
return JSON.parse(Buffer.from(content, "base64").toString("utf8"));
|
|
1723
|
+
} catch {
|
|
1724
|
+
return null;
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1729
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1730
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1731
|
+
*
|
|
1732
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1733
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1734
|
+
*
|
|
1735
|
+
* @example
|
|
1736
|
+
* // LangChain chain
|
|
1737
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1738
|
+
* session: 'btc-analysis',
|
|
1739
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1740
|
+
* })
|
|
1741
|
+
*
|
|
1742
|
+
* // Plain async function (also works)
|
|
1743
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1744
|
+
*/
|
|
1745
|
+
async run(chainOrFn, input, opts) {
|
|
1746
|
+
const { session, saveKeys = ["memory", "chatHistory", "context", "history"], snapshot = false } = opts;
|
|
1747
|
+
const priorState = await this.restore(session);
|
|
1748
|
+
if (priorState && typeof chainOrFn === "object") {
|
|
1749
|
+
for (const key of saveKeys) {
|
|
1750
|
+
if (priorState[key] !== void 0 && chainOrFn[key] !== void 0) {
|
|
1751
|
+
try {
|
|
1752
|
+
chainOrFn[key] = priorState[key];
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
let result;
|
|
1759
|
+
if (typeof chainOrFn === "function") {
|
|
1760
|
+
result = await chainOrFn(input);
|
|
1761
|
+
} else if (typeof chainOrFn?.invoke === "function") {
|
|
1762
|
+
result = await chainOrFn.invoke(input);
|
|
1763
|
+
} else if (typeof chainOrFn?.call === "function") {
|
|
1764
|
+
result = await chainOrFn.call(input);
|
|
1765
|
+
} else if (typeof chainOrFn?.run === "function") {
|
|
1766
|
+
result = await chainOrFn.run(typeof input === "string" ? input : JSON.stringify(input));
|
|
1767
|
+
} else {
|
|
1768
|
+
throw new Error("chain must have .invoke(), .call(), or .run() method, or be a function");
|
|
1769
|
+
}
|
|
1770
|
+
const state = { _last_run: (/* @__PURE__ */ new Date()).toISOString(), _result_preview: String(result).slice(0, 200) };
|
|
1771
|
+
for (const key of saveKeys) {
|
|
1772
|
+
if (chainOrFn?.[key] !== void 0) {
|
|
1773
|
+
try {
|
|
1774
|
+
state[key] = JSON.parse(JSON.stringify(chainOrFn[key]));
|
|
1775
|
+
} catch {
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
await this.persist(session, state);
|
|
1780
|
+
if (snapshot) {
|
|
1781
|
+
try {
|
|
1782
|
+
await this.sdk.clawfsSnapshot();
|
|
1783
|
+
} catch {
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
return result;
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1790
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1791
|
+
*
|
|
1792
|
+
* @example
|
|
1793
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1794
|
+
* 'get_crypto_price',
|
|
1795
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1796
|
+
* async (symbol: string) => {
|
|
1797
|
+
* const price = await fetchPrice(symbol)
|
|
1798
|
+
* return `${symbol}: ${price}`
|
|
1799
|
+
* }
|
|
1800
|
+
* )
|
|
1801
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1802
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1803
|
+
*/
|
|
1804
|
+
createTool(name, descriptionOrFn, fn) {
|
|
1805
|
+
const description = typeof descriptionOrFn === "string" ? descriptionOrFn : `MoltOS tool: ${name}`;
|
|
1806
|
+
const handler = typeof descriptionOrFn === "function" ? descriptionOrFn : fn;
|
|
1807
|
+
if (!handler) throw new Error("createTool requires a handler function");
|
|
1808
|
+
const sdk = this.sdk;
|
|
1809
|
+
const agentId = this.agentId;
|
|
1810
|
+
return {
|
|
1811
|
+
name,
|
|
1812
|
+
description,
|
|
1813
|
+
// LangChain Tool interface
|
|
1814
|
+
async call(input) {
|
|
1815
|
+
const result = await handler(input);
|
|
1816
|
+
try {
|
|
1817
|
+
await sdk.clawfsWrite(
|
|
1818
|
+
`/agents/${agentId}/langchain/tool-logs/${name}_${Date.now()}.json`,
|
|
1819
|
+
JSON.stringify({ name, input, result: String(result).slice(0, 1e3), timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
1820
|
+
);
|
|
1821
|
+
} catch {
|
|
1822
|
+
}
|
|
1823
|
+
return String(result);
|
|
1824
|
+
},
|
|
1825
|
+
// Also supports .invoke() (LangChain v0.2+)
|
|
1826
|
+
async invoke(input) {
|
|
1827
|
+
const rawInput = typeof input === "string" ? input : input.input;
|
|
1828
|
+
return this.call(rawInput);
|
|
1829
|
+
}
|
|
1830
|
+
};
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1834
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1835
|
+
* on any machine and resume exactly where you left off.
|
|
1836
|
+
*
|
|
1837
|
+
* @example
|
|
1838
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1839
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1840
|
+
*/
|
|
1841
|
+
async checkpoint() {
|
|
1842
|
+
const snap = await this.sdk.clawfsSnapshot();
|
|
1843
|
+
return {
|
|
1844
|
+
snapshot_id: snap.snapshot?.id ?? snap.id ?? "unknown",
|
|
1845
|
+
merkle_root: snap.snapshot?.merkle_root ?? snap.merkle_root ?? "",
|
|
1846
|
+
path: `/agents/${this.agentId}/langchain/`
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Chain multiple LangChain-compatible tools in sequence.
|
|
1851
|
+
* Output of each tool is passed as input to the next.
|
|
1852
|
+
* All intermediate results are logged to ClawFS.
|
|
1853
|
+
*
|
|
1854
|
+
* @example
|
|
1855
|
+
* const pipeline = sdk.langchain.chainTools([fetchTool, analyzeTool, summarizeTool])
|
|
1856
|
+
* const result = await pipeline('BTC/USD')
|
|
1857
|
+
* // fetchTool('BTC/USD') → analyzeTool(fetchResult) → summarizeTool(analyzeResult)
|
|
1858
|
+
*/
|
|
1859
|
+
chainTools(tools) {
|
|
1860
|
+
const sdk = this.sdk;
|
|
1861
|
+
const agentId = this.agentId;
|
|
1862
|
+
return async (input) => {
|
|
1863
|
+
let current = input;
|
|
1864
|
+
const log = [];
|
|
1865
|
+
for (let i = 0; i < tools.length; i++) {
|
|
1866
|
+
const output = await tools[i].call(current);
|
|
1867
|
+
log.push({ tool: i, input: current, output: String(output).slice(0, 500) });
|
|
1868
|
+
current = String(output);
|
|
1869
|
+
}
|
|
1870
|
+
try {
|
|
1871
|
+
await sdk.clawfsWrite(
|
|
1872
|
+
`/agents/${agentId}/langchain/chain-logs/chain_${Date.now()}.json`,
|
|
1873
|
+
JSON.stringify({ tools_count: tools.length, log, final_output: current.slice(0, 1e3) })
|
|
1874
|
+
);
|
|
1875
|
+
} catch {
|
|
1876
|
+
}
|
|
1877
|
+
return current;
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1880
|
+
};
|
|
1629
1881
|
var MoltOS = {
|
|
1630
1882
|
sdk: (apiUrl) => new MoltOSSDK(apiUrl),
|
|
1631
1883
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -191,6 +191,7 @@ var MoltOSSDK = class {
|
|
|
191
191
|
this.trade = new TradeSDK(this);
|
|
192
192
|
this.teams = new TeamsSDK(this);
|
|
193
193
|
this.market = new MarketSDK(this);
|
|
194
|
+
this.langchain = new LangChainSDK(this);
|
|
194
195
|
}
|
|
195
196
|
/**
|
|
196
197
|
* Initialize with existing credentials
|
|
@@ -722,6 +723,10 @@ var WalletSDK = class {
|
|
|
722
723
|
"wallet.escrow_release": "on_escrow_release"
|
|
723
724
|
};
|
|
724
725
|
function dispatch(event) {
|
|
726
|
+
if (callbacks.types?.length) {
|
|
727
|
+
const shortType = event.type.replace("wallet.", "");
|
|
728
|
+
if (!callbacks.types.includes(shortType)) return;
|
|
729
|
+
}
|
|
725
730
|
const handler = HANDLER_MAP[event.type];
|
|
726
731
|
if (handler && callbacks[handler]) callbacks[handler](event);
|
|
727
732
|
callbacks.on_any?.(event);
|
|
@@ -1215,6 +1220,58 @@ var TeamsSDK = class {
|
|
|
1215
1220
|
const data = await this.req("/claw/bus/poll?type=team.invite&limit=20");
|
|
1216
1221
|
return (data.messages ?? []).map((m) => m.payload ?? m);
|
|
1217
1222
|
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Add an agent to an existing team directly (owner only).
|
|
1225
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1226
|
+
*
|
|
1227
|
+
* @example
|
|
1228
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1229
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1230
|
+
*/
|
|
1231
|
+
async add(teamId, agentId) {
|
|
1232
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1233
|
+
method: "POST",
|
|
1234
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Remove an agent from a team (owner only).
|
|
1239
|
+
*
|
|
1240
|
+
* @example
|
|
1241
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1242
|
+
*/
|
|
1243
|
+
async remove(teamId, agentId) {
|
|
1244
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1245
|
+
method: "DELETE",
|
|
1246
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Auto-invite the top N agents from suggest_partners() in one call.
|
|
1251
|
+
* Finds the best skill/TAP matches and sends them all invites.
|
|
1252
|
+
*
|
|
1253
|
+
* @example
|
|
1254
|
+
* await sdk.teams.auto_invite('team_xyz', {
|
|
1255
|
+
* skills: ['quantitative-trading', 'python'],
|
|
1256
|
+
* min_tap: 30,
|
|
1257
|
+
* top: 3,
|
|
1258
|
+
* message: 'Join our quant swarm — recurring trading contracts lined up.'
|
|
1259
|
+
* })
|
|
1260
|
+
*/
|
|
1261
|
+
async auto_invite(teamId, opts) {
|
|
1262
|
+
const { top = 3, message, ...searchOpts } = opts;
|
|
1263
|
+
const partners = await this.suggest_partners({ ...searchOpts, limit: top });
|
|
1264
|
+
const results = [];
|
|
1265
|
+
for (const p of partners.slice(0, top)) {
|
|
1266
|
+
try {
|
|
1267
|
+
await this.invite(teamId, p.agent_id, { message });
|
|
1268
|
+
results.push({ agent_id: p.agent_id, name: p.name, match_score: p.match_score, invited: true });
|
|
1269
|
+
} catch (e) {
|
|
1270
|
+
results.push({ agent_id: p.agent_id, name: p.name, match_score: p.match_score, invited: false, error: e?.message });
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
return results;
|
|
1274
|
+
}
|
|
1218
1275
|
};
|
|
1219
1276
|
var MarketplaceSDK = class {
|
|
1220
1277
|
constructor(sdk) {
|
|
@@ -1466,6 +1523,201 @@ var MarketSDK = class {
|
|
|
1466
1523
|
return this.req("/referral");
|
|
1467
1524
|
}
|
|
1468
1525
|
};
|
|
1526
|
+
var LangChainSDK = class {
|
|
1527
|
+
constructor(sdk) {
|
|
1528
|
+
this.sdk = sdk;
|
|
1529
|
+
}
|
|
1530
|
+
get agentId() {
|
|
1531
|
+
return this.sdk.agentId;
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1535
|
+
* Call this at the end of each chain run to survive session death.
|
|
1536
|
+
*
|
|
1537
|
+
* @example
|
|
1538
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1539
|
+
*/
|
|
1540
|
+
async persist(key, value) {
|
|
1541
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1542
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1543
|
+
const result = await this.sdk.clawfsWrite(path, JSON.stringify(value, null, 2));
|
|
1544
|
+
return { path, cid: result.file?.cid ?? "" };
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1548
|
+
*
|
|
1549
|
+
* @example
|
|
1550
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1551
|
+
* if (state) {
|
|
1552
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1553
|
+
* }
|
|
1554
|
+
*/
|
|
1555
|
+
async restore(key) {
|
|
1556
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1557
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1558
|
+
try {
|
|
1559
|
+
const result = await this.sdk.clawfsRead(path);
|
|
1560
|
+
const content = result.content ?? result.file?.content;
|
|
1561
|
+
if (!content) return null;
|
|
1562
|
+
return JSON.parse(Buffer.from(content, "base64").toString("utf8"));
|
|
1563
|
+
} catch {
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1569
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1570
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1571
|
+
*
|
|
1572
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1573
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1574
|
+
*
|
|
1575
|
+
* @example
|
|
1576
|
+
* // LangChain chain
|
|
1577
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1578
|
+
* session: 'btc-analysis',
|
|
1579
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1580
|
+
* })
|
|
1581
|
+
*
|
|
1582
|
+
* // Plain async function (also works)
|
|
1583
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1584
|
+
*/
|
|
1585
|
+
async run(chainOrFn, input, opts) {
|
|
1586
|
+
const { session, saveKeys = ["memory", "chatHistory", "context", "history"], snapshot = false } = opts;
|
|
1587
|
+
const priorState = await this.restore(session);
|
|
1588
|
+
if (priorState && typeof chainOrFn === "object") {
|
|
1589
|
+
for (const key of saveKeys) {
|
|
1590
|
+
if (priorState[key] !== void 0 && chainOrFn[key] !== void 0) {
|
|
1591
|
+
try {
|
|
1592
|
+
chainOrFn[key] = priorState[key];
|
|
1593
|
+
} catch {
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
let result;
|
|
1599
|
+
if (typeof chainOrFn === "function") {
|
|
1600
|
+
result = await chainOrFn(input);
|
|
1601
|
+
} else if (typeof chainOrFn?.invoke === "function") {
|
|
1602
|
+
result = await chainOrFn.invoke(input);
|
|
1603
|
+
} else if (typeof chainOrFn?.call === "function") {
|
|
1604
|
+
result = await chainOrFn.call(input);
|
|
1605
|
+
} else if (typeof chainOrFn?.run === "function") {
|
|
1606
|
+
result = await chainOrFn.run(typeof input === "string" ? input : JSON.stringify(input));
|
|
1607
|
+
} else {
|
|
1608
|
+
throw new Error("chain must have .invoke(), .call(), or .run() method, or be a function");
|
|
1609
|
+
}
|
|
1610
|
+
const state = { _last_run: (/* @__PURE__ */ new Date()).toISOString(), _result_preview: String(result).slice(0, 200) };
|
|
1611
|
+
for (const key of saveKeys) {
|
|
1612
|
+
if (chainOrFn?.[key] !== void 0) {
|
|
1613
|
+
try {
|
|
1614
|
+
state[key] = JSON.parse(JSON.stringify(chainOrFn[key]));
|
|
1615
|
+
} catch {
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
await this.persist(session, state);
|
|
1620
|
+
if (snapshot) {
|
|
1621
|
+
try {
|
|
1622
|
+
await this.sdk.clawfsSnapshot();
|
|
1623
|
+
} catch {
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
return result;
|
|
1627
|
+
}
|
|
1628
|
+
/**
|
|
1629
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1630
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1631
|
+
*
|
|
1632
|
+
* @example
|
|
1633
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1634
|
+
* 'get_crypto_price',
|
|
1635
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1636
|
+
* async (symbol: string) => {
|
|
1637
|
+
* const price = await fetchPrice(symbol)
|
|
1638
|
+
* return `${symbol}: ${price}`
|
|
1639
|
+
* }
|
|
1640
|
+
* )
|
|
1641
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1642
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1643
|
+
*/
|
|
1644
|
+
createTool(name, descriptionOrFn, fn) {
|
|
1645
|
+
const description = typeof descriptionOrFn === "string" ? descriptionOrFn : `MoltOS tool: ${name}`;
|
|
1646
|
+
const handler = typeof descriptionOrFn === "function" ? descriptionOrFn : fn;
|
|
1647
|
+
if (!handler) throw new Error("createTool requires a handler function");
|
|
1648
|
+
const sdk = this.sdk;
|
|
1649
|
+
const agentId = this.agentId;
|
|
1650
|
+
return {
|
|
1651
|
+
name,
|
|
1652
|
+
description,
|
|
1653
|
+
// LangChain Tool interface
|
|
1654
|
+
async call(input) {
|
|
1655
|
+
const result = await handler(input);
|
|
1656
|
+
try {
|
|
1657
|
+
await sdk.clawfsWrite(
|
|
1658
|
+
`/agents/${agentId}/langchain/tool-logs/${name}_${Date.now()}.json`,
|
|
1659
|
+
JSON.stringify({ name, input, result: String(result).slice(0, 1e3), timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
1660
|
+
);
|
|
1661
|
+
} catch {
|
|
1662
|
+
}
|
|
1663
|
+
return String(result);
|
|
1664
|
+
},
|
|
1665
|
+
// Also supports .invoke() (LangChain v0.2+)
|
|
1666
|
+
async invoke(input) {
|
|
1667
|
+
const rawInput = typeof input === "string" ? input : input.input;
|
|
1668
|
+
return this.call(rawInput);
|
|
1669
|
+
}
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1674
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1675
|
+
* on any machine and resume exactly where you left off.
|
|
1676
|
+
*
|
|
1677
|
+
* @example
|
|
1678
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1679
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1680
|
+
*/
|
|
1681
|
+
async checkpoint() {
|
|
1682
|
+
const snap = await this.sdk.clawfsSnapshot();
|
|
1683
|
+
return {
|
|
1684
|
+
snapshot_id: snap.snapshot?.id ?? snap.id ?? "unknown",
|
|
1685
|
+
merkle_root: snap.snapshot?.merkle_root ?? snap.merkle_root ?? "",
|
|
1686
|
+
path: `/agents/${this.agentId}/langchain/`
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Chain multiple LangChain-compatible tools in sequence.
|
|
1691
|
+
* Output of each tool is passed as input to the next.
|
|
1692
|
+
* All intermediate results are logged to ClawFS.
|
|
1693
|
+
*
|
|
1694
|
+
* @example
|
|
1695
|
+
* const pipeline = sdk.langchain.chainTools([fetchTool, analyzeTool, summarizeTool])
|
|
1696
|
+
* const result = await pipeline('BTC/USD')
|
|
1697
|
+
* // fetchTool('BTC/USD') → analyzeTool(fetchResult) → summarizeTool(analyzeResult)
|
|
1698
|
+
*/
|
|
1699
|
+
chainTools(tools) {
|
|
1700
|
+
const sdk = this.sdk;
|
|
1701
|
+
const agentId = this.agentId;
|
|
1702
|
+
return async (input) => {
|
|
1703
|
+
let current = input;
|
|
1704
|
+
const log = [];
|
|
1705
|
+
for (let i = 0; i < tools.length; i++) {
|
|
1706
|
+
const output = await tools[i].call(current);
|
|
1707
|
+
log.push({ tool: i, input: current, output: String(output).slice(0, 500) });
|
|
1708
|
+
current = String(output);
|
|
1709
|
+
}
|
|
1710
|
+
try {
|
|
1711
|
+
await sdk.clawfsWrite(
|
|
1712
|
+
`/agents/${agentId}/langchain/chain-logs/chain_${Date.now()}.json`,
|
|
1713
|
+
JSON.stringify({ tools_count: tools.length, log, final_output: current.slice(0, 1e3) })
|
|
1714
|
+
);
|
|
1715
|
+
} catch {
|
|
1716
|
+
}
|
|
1717
|
+
return current;
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1469
1721
|
var MoltOS = {
|
|
1470
1722
|
sdk: (apiUrl) => new MoltOSSDK(apiUrl),
|
|
1471
1723
|
/**
|
package/package.json
CHANGED