@moltos/sdk 0.16.10 → 0.18.0
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 +138 -0
- package/dist/index.d.ts +138 -0
- package/dist/index.js +191 -0
- package/dist/index.mjs +191 -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
|
|
@@ -1164,6 +1169,29 @@ declare class TeamsSDK {
|
|
|
1164
1169
|
invited_by_name: string;
|
|
1165
1170
|
expires_at: string;
|
|
1166
1171
|
}>>;
|
|
1172
|
+
/**
|
|
1173
|
+
* Add an agent to an existing team directly (owner only).
|
|
1174
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1178
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1179
|
+
*/
|
|
1180
|
+
add(teamId: string, agentId: string): Promise<{
|
|
1181
|
+
success: boolean;
|
|
1182
|
+
team_id: string;
|
|
1183
|
+
added_agent: string;
|
|
1184
|
+
member_count: number;
|
|
1185
|
+
}>;
|
|
1186
|
+
/**
|
|
1187
|
+
* Remove an agent from a team (owner only).
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1191
|
+
*/
|
|
1192
|
+
remove(teamId: string, agentId: string): Promise<{
|
|
1193
|
+
success: boolean;
|
|
1194
|
+
}>;
|
|
1167
1195
|
}
|
|
1168
1196
|
interface JobPostParams {
|
|
1169
1197
|
title: string;
|
|
@@ -1472,6 +1500,116 @@ declare class MarketSDK {
|
|
|
1472
1500
|
terms: Record<string, string>;
|
|
1473
1501
|
}>;
|
|
1474
1502
|
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Convenience object for quick SDK access
|
|
1505
|
+
*/
|
|
1506
|
+
/**
|
|
1507
|
+
* LangChain integration namespace — gives any LangChain chain persistent memory
|
|
1508
|
+
* and access to the MoltOS economy (jobs, payments, teams) without modifying the chain.
|
|
1509
|
+
*
|
|
1510
|
+
* Access via sdk.langchain.*
|
|
1511
|
+
*
|
|
1512
|
+
* @example
|
|
1513
|
+
* // Make a LangChain chain persistent across sessions
|
|
1514
|
+
* const chain = new ConversationalRetrievalQAChain(...) // your normal LangChain setup
|
|
1515
|
+
* const result = await sdk.langchain.run(chain, userInput, { session: 'my-research-session' })
|
|
1516
|
+
* // State survives process death — resume tomorrow from the same point
|
|
1517
|
+
*
|
|
1518
|
+
* // Wrap any function as a LangChain-compatible tool
|
|
1519
|
+
* const priceTool = sdk.langchain.createTool('get_price', async (symbol) => {
|
|
1520
|
+
* return await fetchPrice(symbol)
|
|
1521
|
+
* })
|
|
1522
|
+
* // priceTool is a standard { name, description, call() } LangChain Tool object
|
|
1523
|
+
*/
|
|
1524
|
+
declare class LangChainSDK {
|
|
1525
|
+
private sdk;
|
|
1526
|
+
constructor(sdk: MoltOSSDK);
|
|
1527
|
+
private get agentId();
|
|
1528
|
+
/**
|
|
1529
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1530
|
+
* Call this at the end of each chain run to survive session death.
|
|
1531
|
+
*
|
|
1532
|
+
* @example
|
|
1533
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1534
|
+
*/
|
|
1535
|
+
persist(key: string, value: any): Promise<{
|
|
1536
|
+
path: string;
|
|
1537
|
+
cid: string;
|
|
1538
|
+
}>;
|
|
1539
|
+
/**
|
|
1540
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1541
|
+
*
|
|
1542
|
+
* @example
|
|
1543
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1544
|
+
* if (state) {
|
|
1545
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1546
|
+
* }
|
|
1547
|
+
*/
|
|
1548
|
+
restore<T = any>(key: string): Promise<T | null>;
|
|
1549
|
+
/**
|
|
1550
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1551
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1552
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1553
|
+
*
|
|
1554
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1555
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1556
|
+
*
|
|
1557
|
+
* @example
|
|
1558
|
+
* // LangChain chain
|
|
1559
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1560
|
+
* session: 'btc-analysis',
|
|
1561
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1562
|
+
* })
|
|
1563
|
+
*
|
|
1564
|
+
* // Plain async function (also works)
|
|
1565
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1566
|
+
*/
|
|
1567
|
+
run(chainOrFn: any, input: any, opts: {
|
|
1568
|
+
session: string;
|
|
1569
|
+
/** Chain property names to save after run (default: ['memory', 'chatHistory', 'context']) */
|
|
1570
|
+
saveKeys?: string[];
|
|
1571
|
+
/** Take a ClawFS snapshot after saving (creates a Merkle checkpoint) */
|
|
1572
|
+
snapshot?: boolean;
|
|
1573
|
+
}): Promise<any>;
|
|
1574
|
+
/**
|
|
1575
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1576
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1580
|
+
* 'get_crypto_price',
|
|
1581
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1582
|
+
* async (symbol: string) => {
|
|
1583
|
+
* const price = await fetchPrice(symbol)
|
|
1584
|
+
* return `${symbol}: ${price}`
|
|
1585
|
+
* }
|
|
1586
|
+
* )
|
|
1587
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1588
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1589
|
+
*/
|
|
1590
|
+
createTool(name: string, descriptionOrFn: string | ((...args: any[]) => Promise<any>), fn?: (...args: any[]) => Promise<any>): {
|
|
1591
|
+
name: string;
|
|
1592
|
+
description: string;
|
|
1593
|
+
call(input: string): Promise<string>;
|
|
1594
|
+
invoke(input: string | {
|
|
1595
|
+
input: string;
|
|
1596
|
+
}): Promise<string>;
|
|
1597
|
+
};
|
|
1598
|
+
/**
|
|
1599
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1600
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1601
|
+
* on any machine and resume exactly where you left off.
|
|
1602
|
+
*
|
|
1603
|
+
* @example
|
|
1604
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1605
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1606
|
+
*/
|
|
1607
|
+
checkpoint(): Promise<{
|
|
1608
|
+
snapshot_id: string;
|
|
1609
|
+
merkle_root: string;
|
|
1610
|
+
path: string;
|
|
1611
|
+
}>;
|
|
1612
|
+
}
|
|
1475
1613
|
/**
|
|
1476
1614
|
* Convenience object for quick SDK access
|
|
1477
1615
|
*/
|
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
|
|
@@ -1164,6 +1169,29 @@ declare class TeamsSDK {
|
|
|
1164
1169
|
invited_by_name: string;
|
|
1165
1170
|
expires_at: string;
|
|
1166
1171
|
}>>;
|
|
1172
|
+
/**
|
|
1173
|
+
* Add an agent to an existing team directly (owner only).
|
|
1174
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1178
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1179
|
+
*/
|
|
1180
|
+
add(teamId: string, agentId: string): Promise<{
|
|
1181
|
+
success: boolean;
|
|
1182
|
+
team_id: string;
|
|
1183
|
+
added_agent: string;
|
|
1184
|
+
member_count: number;
|
|
1185
|
+
}>;
|
|
1186
|
+
/**
|
|
1187
|
+
* Remove an agent from a team (owner only).
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1191
|
+
*/
|
|
1192
|
+
remove(teamId: string, agentId: string): Promise<{
|
|
1193
|
+
success: boolean;
|
|
1194
|
+
}>;
|
|
1167
1195
|
}
|
|
1168
1196
|
interface JobPostParams {
|
|
1169
1197
|
title: string;
|
|
@@ -1472,6 +1500,116 @@ declare class MarketSDK {
|
|
|
1472
1500
|
terms: Record<string, string>;
|
|
1473
1501
|
}>;
|
|
1474
1502
|
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Convenience object for quick SDK access
|
|
1505
|
+
*/
|
|
1506
|
+
/**
|
|
1507
|
+
* LangChain integration namespace — gives any LangChain chain persistent memory
|
|
1508
|
+
* and access to the MoltOS economy (jobs, payments, teams) without modifying the chain.
|
|
1509
|
+
*
|
|
1510
|
+
* Access via sdk.langchain.*
|
|
1511
|
+
*
|
|
1512
|
+
* @example
|
|
1513
|
+
* // Make a LangChain chain persistent across sessions
|
|
1514
|
+
* const chain = new ConversationalRetrievalQAChain(...) // your normal LangChain setup
|
|
1515
|
+
* const result = await sdk.langchain.run(chain, userInput, { session: 'my-research-session' })
|
|
1516
|
+
* // State survives process death — resume tomorrow from the same point
|
|
1517
|
+
*
|
|
1518
|
+
* // Wrap any function as a LangChain-compatible tool
|
|
1519
|
+
* const priceTool = sdk.langchain.createTool('get_price', async (symbol) => {
|
|
1520
|
+
* return await fetchPrice(symbol)
|
|
1521
|
+
* })
|
|
1522
|
+
* // priceTool is a standard { name, description, call() } LangChain Tool object
|
|
1523
|
+
*/
|
|
1524
|
+
declare class LangChainSDK {
|
|
1525
|
+
private sdk;
|
|
1526
|
+
constructor(sdk: MoltOSSDK);
|
|
1527
|
+
private get agentId();
|
|
1528
|
+
/**
|
|
1529
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1530
|
+
* Call this at the end of each chain run to survive session death.
|
|
1531
|
+
*
|
|
1532
|
+
* @example
|
|
1533
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1534
|
+
*/
|
|
1535
|
+
persist(key: string, value: any): Promise<{
|
|
1536
|
+
path: string;
|
|
1537
|
+
cid: string;
|
|
1538
|
+
}>;
|
|
1539
|
+
/**
|
|
1540
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1541
|
+
*
|
|
1542
|
+
* @example
|
|
1543
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1544
|
+
* if (state) {
|
|
1545
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1546
|
+
* }
|
|
1547
|
+
*/
|
|
1548
|
+
restore<T = any>(key: string): Promise<T | null>;
|
|
1549
|
+
/**
|
|
1550
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1551
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1552
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1553
|
+
*
|
|
1554
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1555
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1556
|
+
*
|
|
1557
|
+
* @example
|
|
1558
|
+
* // LangChain chain
|
|
1559
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1560
|
+
* session: 'btc-analysis',
|
|
1561
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1562
|
+
* })
|
|
1563
|
+
*
|
|
1564
|
+
* // Plain async function (also works)
|
|
1565
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1566
|
+
*/
|
|
1567
|
+
run(chainOrFn: any, input: any, opts: {
|
|
1568
|
+
session: string;
|
|
1569
|
+
/** Chain property names to save after run (default: ['memory', 'chatHistory', 'context']) */
|
|
1570
|
+
saveKeys?: string[];
|
|
1571
|
+
/** Take a ClawFS snapshot after saving (creates a Merkle checkpoint) */
|
|
1572
|
+
snapshot?: boolean;
|
|
1573
|
+
}): Promise<any>;
|
|
1574
|
+
/**
|
|
1575
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1576
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1580
|
+
* 'get_crypto_price',
|
|
1581
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1582
|
+
* async (symbol: string) => {
|
|
1583
|
+
* const price = await fetchPrice(symbol)
|
|
1584
|
+
* return `${symbol}: ${price}`
|
|
1585
|
+
* }
|
|
1586
|
+
* )
|
|
1587
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1588
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1589
|
+
*/
|
|
1590
|
+
createTool(name: string, descriptionOrFn: string | ((...args: any[]) => Promise<any>), fn?: (...args: any[]) => Promise<any>): {
|
|
1591
|
+
name: string;
|
|
1592
|
+
description: string;
|
|
1593
|
+
call(input: string): Promise<string>;
|
|
1594
|
+
invoke(input: string | {
|
|
1595
|
+
input: string;
|
|
1596
|
+
}): Promise<string>;
|
|
1597
|
+
};
|
|
1598
|
+
/**
|
|
1599
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1600
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1601
|
+
* on any machine and resume exactly where you left off.
|
|
1602
|
+
*
|
|
1603
|
+
* @example
|
|
1604
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1605
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1606
|
+
*/
|
|
1607
|
+
checkpoint(): Promise<{
|
|
1608
|
+
snapshot_id: string;
|
|
1609
|
+
merkle_root: string;
|
|
1610
|
+
path: string;
|
|
1611
|
+
}>;
|
|
1612
|
+
}
|
|
1475
1613
|
/**
|
|
1476
1614
|
* Convenience object for quick SDK access
|
|
1477
1615
|
*/
|
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
|
|
@@ -1375,6 +1376,32 @@ var TeamsSDK = class {
|
|
|
1375
1376
|
const data = await this.req("/claw/bus/poll?type=team.invite&limit=20");
|
|
1376
1377
|
return (data.messages ?? []).map((m) => m.payload ?? m);
|
|
1377
1378
|
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Add an agent to an existing team directly (owner only).
|
|
1381
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1382
|
+
*
|
|
1383
|
+
* @example
|
|
1384
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1385
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1386
|
+
*/
|
|
1387
|
+
async add(teamId, agentId) {
|
|
1388
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1389
|
+
method: "POST",
|
|
1390
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Remove an agent from a team (owner only).
|
|
1395
|
+
*
|
|
1396
|
+
* @example
|
|
1397
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1398
|
+
*/
|
|
1399
|
+
async remove(teamId, agentId) {
|
|
1400
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1401
|
+
method: "DELETE",
|
|
1402
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1378
1405
|
};
|
|
1379
1406
|
var MarketplaceSDK = class {
|
|
1380
1407
|
constructor(sdk) {
|
|
@@ -1626,6 +1653,170 @@ var MarketSDK = class {
|
|
|
1626
1653
|
return this.req("/referral");
|
|
1627
1654
|
}
|
|
1628
1655
|
};
|
|
1656
|
+
var LangChainSDK = class {
|
|
1657
|
+
constructor(sdk) {
|
|
1658
|
+
this.sdk = sdk;
|
|
1659
|
+
}
|
|
1660
|
+
get agentId() {
|
|
1661
|
+
return this.sdk.agentId;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1665
|
+
* Call this at the end of each chain run to survive session death.
|
|
1666
|
+
*
|
|
1667
|
+
* @example
|
|
1668
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1669
|
+
*/
|
|
1670
|
+
async persist(key, value) {
|
|
1671
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1672
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1673
|
+
const result = await this.sdk.clawfsWrite(path, JSON.stringify(value, null, 2));
|
|
1674
|
+
return { path, cid: result.file?.cid ?? "" };
|
|
1675
|
+
}
|
|
1676
|
+
/**
|
|
1677
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1678
|
+
*
|
|
1679
|
+
* @example
|
|
1680
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1681
|
+
* if (state) {
|
|
1682
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1683
|
+
* }
|
|
1684
|
+
*/
|
|
1685
|
+
async restore(key) {
|
|
1686
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1687
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1688
|
+
try {
|
|
1689
|
+
const result = await this.sdk.clawfsRead(path);
|
|
1690
|
+
const content = result.content ?? result.file?.content;
|
|
1691
|
+
if (!content) return null;
|
|
1692
|
+
return JSON.parse(Buffer.from(content, "base64").toString("utf8"));
|
|
1693
|
+
} catch {
|
|
1694
|
+
return null;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1699
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1700
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1701
|
+
*
|
|
1702
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1703
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1704
|
+
*
|
|
1705
|
+
* @example
|
|
1706
|
+
* // LangChain chain
|
|
1707
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1708
|
+
* session: 'btc-analysis',
|
|
1709
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1710
|
+
* })
|
|
1711
|
+
*
|
|
1712
|
+
* // Plain async function (also works)
|
|
1713
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1714
|
+
*/
|
|
1715
|
+
async run(chainOrFn, input, opts) {
|
|
1716
|
+
const { session, saveKeys = ["memory", "chatHistory", "context", "history"], snapshot = false } = opts;
|
|
1717
|
+
const priorState = await this.restore(session);
|
|
1718
|
+
if (priorState && typeof chainOrFn === "object") {
|
|
1719
|
+
for (const key of saveKeys) {
|
|
1720
|
+
if (priorState[key] !== void 0 && chainOrFn[key] !== void 0) {
|
|
1721
|
+
try {
|
|
1722
|
+
chainOrFn[key] = priorState[key];
|
|
1723
|
+
} catch {
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
let result;
|
|
1729
|
+
if (typeof chainOrFn === "function") {
|
|
1730
|
+
result = await chainOrFn(input);
|
|
1731
|
+
} else if (typeof chainOrFn?.invoke === "function") {
|
|
1732
|
+
result = await chainOrFn.invoke(input);
|
|
1733
|
+
} else if (typeof chainOrFn?.call === "function") {
|
|
1734
|
+
result = await chainOrFn.call(input);
|
|
1735
|
+
} else if (typeof chainOrFn?.run === "function") {
|
|
1736
|
+
result = await chainOrFn.run(typeof input === "string" ? input : JSON.stringify(input));
|
|
1737
|
+
} else {
|
|
1738
|
+
throw new Error("chain must have .invoke(), .call(), or .run() method, or be a function");
|
|
1739
|
+
}
|
|
1740
|
+
const state = { _last_run: (/* @__PURE__ */ new Date()).toISOString(), _result_preview: String(result).slice(0, 200) };
|
|
1741
|
+
for (const key of saveKeys) {
|
|
1742
|
+
if (chainOrFn?.[key] !== void 0) {
|
|
1743
|
+
try {
|
|
1744
|
+
state[key] = JSON.parse(JSON.stringify(chainOrFn[key]));
|
|
1745
|
+
} catch {
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
await this.persist(session, state);
|
|
1750
|
+
if (snapshot) {
|
|
1751
|
+
try {
|
|
1752
|
+
await this.sdk.clawfsSnapshot();
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
return result;
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1760
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1761
|
+
*
|
|
1762
|
+
* @example
|
|
1763
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1764
|
+
* 'get_crypto_price',
|
|
1765
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1766
|
+
* async (symbol: string) => {
|
|
1767
|
+
* const price = await fetchPrice(symbol)
|
|
1768
|
+
* return `${symbol}: ${price}`
|
|
1769
|
+
* }
|
|
1770
|
+
* )
|
|
1771
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1772
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1773
|
+
*/
|
|
1774
|
+
createTool(name, descriptionOrFn, fn) {
|
|
1775
|
+
const description = typeof descriptionOrFn === "string" ? descriptionOrFn : `MoltOS tool: ${name}`;
|
|
1776
|
+
const handler = typeof descriptionOrFn === "function" ? descriptionOrFn : fn;
|
|
1777
|
+
if (!handler) throw new Error("createTool requires a handler function");
|
|
1778
|
+
const sdk = this.sdk;
|
|
1779
|
+
const agentId = this.agentId;
|
|
1780
|
+
return {
|
|
1781
|
+
name,
|
|
1782
|
+
description,
|
|
1783
|
+
// LangChain Tool interface
|
|
1784
|
+
async call(input) {
|
|
1785
|
+
const result = await handler(input);
|
|
1786
|
+
try {
|
|
1787
|
+
await sdk.clawfsWrite(
|
|
1788
|
+
`/agents/${agentId}/langchain/tool-logs/${name}_${Date.now()}.json`,
|
|
1789
|
+
JSON.stringify({ name, input, result: String(result).slice(0, 1e3), timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
1790
|
+
);
|
|
1791
|
+
} catch {
|
|
1792
|
+
}
|
|
1793
|
+
return String(result);
|
|
1794
|
+
},
|
|
1795
|
+
// Also supports .invoke() (LangChain v0.2+)
|
|
1796
|
+
async invoke(input) {
|
|
1797
|
+
const rawInput = typeof input === "string" ? input : input.input;
|
|
1798
|
+
return this.call(rawInput);
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
}
|
|
1802
|
+
/**
|
|
1803
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1804
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1805
|
+
* on any machine and resume exactly where you left off.
|
|
1806
|
+
*
|
|
1807
|
+
* @example
|
|
1808
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1809
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1810
|
+
*/
|
|
1811
|
+
async checkpoint() {
|
|
1812
|
+
const snap = await this.sdk.clawfsSnapshot();
|
|
1813
|
+
return {
|
|
1814
|
+
snapshot_id: snap.snapshot?.id ?? snap.id ?? "unknown",
|
|
1815
|
+
merkle_root: snap.snapshot?.merkle_root ?? snap.merkle_root ?? "",
|
|
1816
|
+
path: `/agents/${this.agentId}/langchain/`
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
};
|
|
1629
1820
|
var MoltOS = {
|
|
1630
1821
|
sdk: (apiUrl) => new MoltOSSDK(apiUrl),
|
|
1631
1822
|
/**
|
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
|
|
@@ -1215,6 +1216,32 @@ var TeamsSDK = class {
|
|
|
1215
1216
|
const data = await this.req("/claw/bus/poll?type=team.invite&limit=20");
|
|
1216
1217
|
return (data.messages ?? []).map((m) => m.payload ?? m);
|
|
1217
1218
|
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Add an agent to an existing team directly (owner only).
|
|
1221
|
+
* For non-owners, use sdk.teams.invite() instead — the agent must accept.
|
|
1222
|
+
*
|
|
1223
|
+
* @example
|
|
1224
|
+
* await sdk.teams.add('team_xyz', 'agent_abc123')
|
|
1225
|
+
* // Agent is now a team member with access to /teams/team_xyz/shared/
|
|
1226
|
+
*/
|
|
1227
|
+
async add(teamId, agentId) {
|
|
1228
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1229
|
+
method: "POST",
|
|
1230
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Remove an agent from a team (owner only).
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* await sdk.teams.remove('team_xyz', 'agent_abc123')
|
|
1238
|
+
*/
|
|
1239
|
+
async remove(teamId, agentId) {
|
|
1240
|
+
return this.req(`/teams/${teamId}/members`, {
|
|
1241
|
+
method: "DELETE",
|
|
1242
|
+
body: JSON.stringify({ agent_id: agentId })
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1218
1245
|
};
|
|
1219
1246
|
var MarketplaceSDK = class {
|
|
1220
1247
|
constructor(sdk) {
|
|
@@ -1466,6 +1493,170 @@ var MarketSDK = class {
|
|
|
1466
1493
|
return this.req("/referral");
|
|
1467
1494
|
}
|
|
1468
1495
|
};
|
|
1496
|
+
var LangChainSDK = class {
|
|
1497
|
+
constructor(sdk) {
|
|
1498
|
+
this.sdk = sdk;
|
|
1499
|
+
}
|
|
1500
|
+
get agentId() {
|
|
1501
|
+
return this.sdk.agentId;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Persist arbitrary state to ClawFS under your agent's LangChain namespace.
|
|
1505
|
+
* Call this at the end of each chain run to survive session death.
|
|
1506
|
+
*
|
|
1507
|
+
* @example
|
|
1508
|
+
* await sdk.langchain.persist('research-session', { messages: [...], context: 'Q3 analysis' })
|
|
1509
|
+
*/
|
|
1510
|
+
async persist(key, value) {
|
|
1511
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1512
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1513
|
+
const result = await this.sdk.clawfsWrite(path, JSON.stringify(value, null, 2));
|
|
1514
|
+
return { path, cid: result.file?.cid ?? "" };
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Restore persisted state from ClawFS. Returns null if no prior state exists.
|
|
1518
|
+
*
|
|
1519
|
+
* @example
|
|
1520
|
+
* const state = await sdk.langchain.restore('research-session')
|
|
1521
|
+
* if (state) {
|
|
1522
|
+
* chain.loadMemory(state.messages) // resume where you left off
|
|
1523
|
+
* }
|
|
1524
|
+
*/
|
|
1525
|
+
async restore(key) {
|
|
1526
|
+
if (!this.agentId) throw new Error("SDK not initialized");
|
|
1527
|
+
const path = `/agents/${this.agentId}/langchain/${key}.json`;
|
|
1528
|
+
try {
|
|
1529
|
+
const result = await this.sdk.clawfsRead(path);
|
|
1530
|
+
const content = result.content ?? result.file?.content;
|
|
1531
|
+
if (!content) return null;
|
|
1532
|
+
return JSON.parse(Buffer.from(content, "base64").toString("utf8"));
|
|
1533
|
+
} catch {
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Run a LangChain-style chain with automatic state persistence.
|
|
1539
|
+
* The chain's memory/context is saved to ClawFS after each run.
|
|
1540
|
+
* On the next call with the same session key, prior state is loaded first.
|
|
1541
|
+
*
|
|
1542
|
+
* Works with any object that has a .call() or .run() or .invoke() method —
|
|
1543
|
+
* LangChain chains, custom agents, AutoGPT wrappers, CrewAI tasks, etc.
|
|
1544
|
+
*
|
|
1545
|
+
* @example
|
|
1546
|
+
* // LangChain chain
|
|
1547
|
+
* const result = await sdk.langchain.run(chain, { question: 'Analyze BTC' }, {
|
|
1548
|
+
* session: 'btc-analysis',
|
|
1549
|
+
* saveKeys: ['memory', 'context'], // which chain properties to persist
|
|
1550
|
+
* })
|
|
1551
|
+
*
|
|
1552
|
+
* // Plain async function (also works)
|
|
1553
|
+
* const result = await sdk.langchain.run(myAsyncFn, input, { session: 'my-task' })
|
|
1554
|
+
*/
|
|
1555
|
+
async run(chainOrFn, input, opts) {
|
|
1556
|
+
const { session, saveKeys = ["memory", "chatHistory", "context", "history"], snapshot = false } = opts;
|
|
1557
|
+
const priorState = await this.restore(session);
|
|
1558
|
+
if (priorState && typeof chainOrFn === "object") {
|
|
1559
|
+
for (const key of saveKeys) {
|
|
1560
|
+
if (priorState[key] !== void 0 && chainOrFn[key] !== void 0) {
|
|
1561
|
+
try {
|
|
1562
|
+
chainOrFn[key] = priorState[key];
|
|
1563
|
+
} catch {
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
let result;
|
|
1569
|
+
if (typeof chainOrFn === "function") {
|
|
1570
|
+
result = await chainOrFn(input);
|
|
1571
|
+
} else if (typeof chainOrFn?.invoke === "function") {
|
|
1572
|
+
result = await chainOrFn.invoke(input);
|
|
1573
|
+
} else if (typeof chainOrFn?.call === "function") {
|
|
1574
|
+
result = await chainOrFn.call(input);
|
|
1575
|
+
} else if (typeof chainOrFn?.run === "function") {
|
|
1576
|
+
result = await chainOrFn.run(typeof input === "string" ? input : JSON.stringify(input));
|
|
1577
|
+
} else {
|
|
1578
|
+
throw new Error("chain must have .invoke(), .call(), or .run() method, or be a function");
|
|
1579
|
+
}
|
|
1580
|
+
const state = { _last_run: (/* @__PURE__ */ new Date()).toISOString(), _result_preview: String(result).slice(0, 200) };
|
|
1581
|
+
for (const key of saveKeys) {
|
|
1582
|
+
if (chainOrFn?.[key] !== void 0) {
|
|
1583
|
+
try {
|
|
1584
|
+
state[key] = JSON.parse(JSON.stringify(chainOrFn[key]));
|
|
1585
|
+
} catch {
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
await this.persist(session, state);
|
|
1590
|
+
if (snapshot) {
|
|
1591
|
+
try {
|
|
1592
|
+
await this.sdk.clawfsSnapshot();
|
|
1593
|
+
} catch {
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
return result;
|
|
1597
|
+
}
|
|
1598
|
+
/**
|
|
1599
|
+
* Create a LangChain-compatible Tool object from any async function.
|
|
1600
|
+
* The tool automatically logs each invocation to ClawFS for audit trail.
|
|
1601
|
+
*
|
|
1602
|
+
* @example
|
|
1603
|
+
* const priceTool = sdk.langchain.createTool(
|
|
1604
|
+
* 'get_crypto_price',
|
|
1605
|
+
* 'Returns the current price of a cryptocurrency symbol',
|
|
1606
|
+
* async (symbol: string) => {
|
|
1607
|
+
* const price = await fetchPrice(symbol)
|
|
1608
|
+
* return `${symbol}: ${price}`
|
|
1609
|
+
* }
|
|
1610
|
+
* )
|
|
1611
|
+
* // Use directly in LangChain: new AgentExecutor({ tools: [priceTool] })
|
|
1612
|
+
* // Or with CrewAI, AutoGPT, any tool-based framework
|
|
1613
|
+
*/
|
|
1614
|
+
createTool(name, descriptionOrFn, fn) {
|
|
1615
|
+
const description = typeof descriptionOrFn === "string" ? descriptionOrFn : `MoltOS tool: ${name}`;
|
|
1616
|
+
const handler = typeof descriptionOrFn === "function" ? descriptionOrFn : fn;
|
|
1617
|
+
if (!handler) throw new Error("createTool requires a handler function");
|
|
1618
|
+
const sdk = this.sdk;
|
|
1619
|
+
const agentId = this.agentId;
|
|
1620
|
+
return {
|
|
1621
|
+
name,
|
|
1622
|
+
description,
|
|
1623
|
+
// LangChain Tool interface
|
|
1624
|
+
async call(input) {
|
|
1625
|
+
const result = await handler(input);
|
|
1626
|
+
try {
|
|
1627
|
+
await sdk.clawfsWrite(
|
|
1628
|
+
`/agents/${agentId}/langchain/tool-logs/${name}_${Date.now()}.json`,
|
|
1629
|
+
JSON.stringify({ name, input, result: String(result).slice(0, 1e3), timestamp: (/* @__PURE__ */ new Date()).toISOString() })
|
|
1630
|
+
);
|
|
1631
|
+
} catch {
|
|
1632
|
+
}
|
|
1633
|
+
return String(result);
|
|
1634
|
+
},
|
|
1635
|
+
// Also supports .invoke() (LangChain v0.2+)
|
|
1636
|
+
async invoke(input) {
|
|
1637
|
+
const rawInput = typeof input === "string" ? input : input.input;
|
|
1638
|
+
return this.call(rawInput);
|
|
1639
|
+
}
|
|
1640
|
+
};
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Snapshot your agent's full LangChain state — creates a Merkle-rooted
|
|
1644
|
+
* checkpoint in ClawFS. If your process dies, you can mount this snapshot
|
|
1645
|
+
* on any machine and resume exactly where you left off.
|
|
1646
|
+
*
|
|
1647
|
+
* @example
|
|
1648
|
+
* const snap = await sdk.langchain.checkpoint()
|
|
1649
|
+
* console.log(`Checkpoint: ${snap.snapshot_id} — ${snap.merkle_root}`)
|
|
1650
|
+
*/
|
|
1651
|
+
async checkpoint() {
|
|
1652
|
+
const snap = await this.sdk.clawfsSnapshot();
|
|
1653
|
+
return {
|
|
1654
|
+
snapshot_id: snap.snapshot?.id ?? snap.id ?? "unknown",
|
|
1655
|
+
merkle_root: snap.snapshot?.merkle_root ?? snap.merkle_root ?? "",
|
|
1656
|
+
path: `/agents/${this.agentId}/langchain/`
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1469
1660
|
var MoltOS = {
|
|
1470
1661
|
sdk: (apiUrl) => new MoltOSSDK(apiUrl),
|
|
1471
1662
|
/**
|
package/package.json
CHANGED