@tangle-network/tcloud 0.4.12 → 0.4.14

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/mcp.js ADDED
@@ -0,0 +1,207 @@
1
+ import {
2
+ packageVersion
3
+ } from "./chunk-GHMW4RWJ.js";
4
+
5
+ // src/mcp.ts
6
+ import * as readline from "readline";
7
+ var SEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily", "brave"]);
8
+ var RESEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily"]);
9
+ var RECENCY_WINDOWS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
10
+ var SUPPORTED_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set(["2025-06-18", "2025-03-26"]);
11
+ var DEFAULT_PROTOCOL_VERSION = "2025-06-18";
12
+ var DOMAIN_FILTER_SCHEMA = {
13
+ type: "array",
14
+ items: { type: "string" }
15
+ };
16
+ var TOOLS = [
17
+ {
18
+ name: "web_search",
19
+ description: "Search the web via the Tangle router and return live results (title, url, snippet). Use it to find primary sources and to VERIFY that a citation (paper, PMID/DOI, patent, fact) actually exists before relying on it.",
20
+ inputSchema: {
21
+ type: "object",
22
+ properties: {
23
+ query: { type: "string", description: "The search query." },
24
+ provider: {
25
+ type: "string",
26
+ description: "Optional provider: exa | parallel | perplexity | tavily | brave | you."
27
+ },
28
+ maxResults: { type: "number", description: "Optional max number of results." },
29
+ recency: { type: "string", description: "Optional recency window: day | week | month | year." },
30
+ includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict results to these domains." },
31
+ excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop results from these domains." }
32
+ },
33
+ required: ["query"]
34
+ }
35
+ },
36
+ {
37
+ name: "deep_research",
38
+ description: 'Run a multi-step DEEP RESEARCH task via the Tangle router: the provider reads many sources and returns one synthesized answer with citations. Slower and costlier than web_search \u2014 use it for questions that need cross-source synthesis (current API/version landscapes, comparisons, "state of X"), not single-fact lookups.',
39
+ inputSchema: {
40
+ type: "object",
41
+ properties: {
42
+ query: { type: "string", description: "The research question." },
43
+ provider: {
44
+ type: "string",
45
+ description: "Optional provider: you | exa | perplexity | tavily | parallel."
46
+ },
47
+ effort: {
48
+ type: "string",
49
+ description: "Optional depth/cost dial (provider-specific): you lite|standard|deep|exhaustive \xB7 perplexity minimal|low|medium|high \xB7 exa deep-lite|deep|deep-reasoning \xB7 tavily mini|pro|auto \xB7 parallel lite|base|core|pro|ultra."
50
+ },
51
+ maxResults: { type: "number", description: "Optional max number of supporting sources." },
52
+ searchRecency: { type: "string", description: "Optional recency window: day | week | month | year." },
53
+ includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict sources to these domains." },
54
+ excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop sources from these domains." },
55
+ outputSchema: {
56
+ type: "object",
57
+ description: "Optional JSON schema requesting structured output from the provider."
58
+ }
59
+ },
60
+ required: ["query"]
61
+ }
62
+ }
63
+ ];
64
+ var InvalidParams = class extends Error {
65
+ };
66
+ function optionalMaxResults(value) {
67
+ if (value == null) return void 0;
68
+ const n = Number(value);
69
+ return Number.isFinite(n) && n >= 0 ? n : void 0;
70
+ }
71
+ function requireEnum(value, allowed, label) {
72
+ if (value == null) return void 0;
73
+ if (typeof value !== "string" || !allowed.has(value)) {
74
+ throw new InvalidParams(`invalid ${label}: ${String(value)}`);
75
+ }
76
+ return value;
77
+ }
78
+ function optionalDomains(value) {
79
+ if (!Array.isArray(value)) return void 0;
80
+ const domains = value.filter((d) => typeof d === "string");
81
+ return domains.length ? domains : void 0;
82
+ }
83
+ async function runMcpServer(client, opts = {}) {
84
+ const input = opts.input ?? process.stdin;
85
+ const output = opts.output ?? process.stdout;
86
+ const rl = readline.createInterface({ input });
87
+ const send = (msg) => {
88
+ output.write(`${JSON.stringify(msg)}
89
+ `);
90
+ };
91
+ const ok = (id, result) => send({ jsonrpc: "2.0", id, result });
92
+ const fail = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });
93
+ const toolError = (id, message) => ok(id, { content: [{ type: "text", text: message }], isError: true });
94
+ process.stderr.write("tcloud mcp: web_search + deep_research server ready (stdio)\n");
95
+ async function handleRequest(req) {
96
+ const { id, method, params } = req;
97
+ try {
98
+ if (method === "initialize") {
99
+ const requested = params?.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;
100
+ const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : DEFAULT_PROTOCOL_VERSION;
101
+ ok(id, {
102
+ protocolVersion,
103
+ capabilities: { tools: {} },
104
+ serverInfo: { name: "tangle-tcloud", version: packageVersion() }
105
+ });
106
+ } else if (method === "tools/list") {
107
+ ok(id, { tools: TOOLS });
108
+ } else if (method === "tools/call") {
109
+ const name = params?.name;
110
+ if (name === "web_search") {
111
+ await handleWebSearch(id, params?.arguments ?? {});
112
+ } else if (name === "deep_research") {
113
+ await handleDeepResearch(id, params?.arguments ?? {});
114
+ } else {
115
+ fail(id, -32602, `unknown tool: ${String(name)}`);
116
+ }
117
+ } else {
118
+ fail(id, -32601, `method not found: ${String(method)}`);
119
+ }
120
+ } catch (e) {
121
+ if (e instanceof InvalidParams) {
122
+ fail(id, -32602, e.message);
123
+ } else {
124
+ fail(id, -32603, e instanceof Error ? e.message : String(e));
125
+ }
126
+ }
127
+ }
128
+ async function handleWebSearch(id, args) {
129
+ const query = String(args.query ?? "").trim();
130
+ if (!query) {
131
+ fail(id, -32602, 'web_search requires a non-empty "query"');
132
+ return;
133
+ }
134
+ const provider = requireEnum(args.provider, SEARCH_PROVIDERS, "provider");
135
+ const searchRecency = requireEnum(args.recency, RECENCY_WINDOWS, "recency");
136
+ const maxResults = optionalMaxResults(args.maxResults);
137
+ const includeDomains = optionalDomains(args.includeDomains);
138
+ const excludeDomains = optionalDomains(args.excludeDomains);
139
+ try {
140
+ const resp = await client.search({
141
+ query,
142
+ ...provider ? { provider } : {},
143
+ ...maxResults != null ? { maxResults } : {},
144
+ ...searchRecency ? { searchRecency } : {},
145
+ ...includeDomains ? { includeDomains } : {},
146
+ ...excludeDomains ? { excludeDomains } : {}
147
+ });
148
+ const hits = resp.data ?? [];
149
+ const text = hits.length ? hits.map((h, i) => `${i + 1}. ${h.title}
150
+ ${h.url}${h.snippet ? `
151
+ ${h.snippet}` : ""}`).join("\n\n") : `No results for "${resp.query ?? query}".`;
152
+ ok(id, { content: [{ type: "text", text }] });
153
+ } catch (e) {
154
+ toolError(id, e instanceof Error ? e.message : String(e));
155
+ }
156
+ }
157
+ async function handleDeepResearch(id, args) {
158
+ const query = String(args.query ?? "").trim();
159
+ if (!query) {
160
+ fail(id, -32602, 'deep_research requires a non-empty "query"');
161
+ return;
162
+ }
163
+ const provider = requireEnum(args.provider, RESEARCH_PROVIDERS, "provider");
164
+ const searchRecency = requireEnum(args.searchRecency, RECENCY_WINDOWS, "searchRecency");
165
+ const maxResults = optionalMaxResults(args.maxResults);
166
+ const includeDomains = optionalDomains(args.includeDomains);
167
+ const excludeDomains = optionalDomains(args.excludeDomains);
168
+ try {
169
+ const resp = await client.research({
170
+ query,
171
+ ...provider ? { provider } : {},
172
+ ...typeof args.effort === "string" ? { effort: args.effort } : {},
173
+ ...maxResults != null ? { maxResults } : {},
174
+ ...searchRecency ? { searchRecency } : {},
175
+ ...includeDomains ? { includeDomains } : {},
176
+ ...excludeDomains ? { excludeDomains } : {},
177
+ ...args.outputSchema !== void 0 ? { outputSchema: args.outputSchema } : {}
178
+ });
179
+ const sources = resp.results ?? [];
180
+ const sourceList = sources.length ? `
181
+
182
+ Sources:
183
+ ${sources.map((h, i) => `${i + 1}. ${h.title}
184
+ ${h.url}`).join("\n")}` : "";
185
+ const text = `${resp.answer ?? ""}${sourceList}`.trim() || `No research result for "${resp.query ?? query}".`;
186
+ ok(id, { content: [{ type: "text", text }] });
187
+ } catch (e) {
188
+ toolError(id, e instanceof Error ? e.message : String(e));
189
+ }
190
+ }
191
+ for await (const line of rl) {
192
+ const trimmed = line.trim();
193
+ if (!trimmed) continue;
194
+ let req;
195
+ try {
196
+ req = JSON.parse(trimmed);
197
+ } catch {
198
+ send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
199
+ continue;
200
+ }
201
+ if (req.id === void 0 || req.id === null) continue;
202
+ void handleRequest(req);
203
+ }
204
+ }
205
+ export {
206
+ runMcpServer
207
+ };
package/dist/shielded.cjs CHANGED
@@ -1039,6 +1039,26 @@ var TCloudClient = class _TCloudClient {
1039
1039
  })
1040
1040
  });
1041
1041
  }
1042
+ /** Run a multi-step deep-research task through Tangle Router billing and
1043
+ * provider routing (POST /v1/research). Slower and costlier than `search` —
1044
+ * the provider synthesizes an answer over many fetches. Pick depth with
1045
+ * `effort` (provider-specific vocabulary; see {@link ResearchOptions.effort}). */
1046
+ async research(options) {
1047
+ return this._request(`${this.baseURL}/research`, {
1048
+ method: "POST",
1049
+ body: JSON.stringify({
1050
+ query: options.query,
1051
+ provider: options.provider,
1052
+ model: options.model,
1053
+ effort: options.effort,
1054
+ maxResults: options.maxResults,
1055
+ searchRecency: options.searchRecency,
1056
+ includeDomains: options.includeDomains,
1057
+ excludeDomains: options.excludeDomains,
1058
+ outputSchema: options.outputSchema
1059
+ })
1060
+ });
1061
+ }
1042
1062
  /** Text-to-speech */
1043
1063
  async speech(options) {
1044
1064
  const res = await this._requestRaw(`${this.baseURL}/audio/speech`, {
@@ -1,5 +1,5 @@
1
1
  import { Hex } from 'viem';
2
- import { a as TCloudConfig, T as TCloudClient, $ as SpendAuth } from './client-CaD5Oal0.cjs';
2
+ import { T as TCloudConfig, a as TCloudClient, a3 as SpendAuth } from './client-CaPP4njg.cjs';
3
3
  import '@tangle-network/sandbox';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { Hex } from 'viem';
2
- import { a as TCloudConfig, T as TCloudClient, $ as SpendAuth } from './client-CaD5Oal0.js';
2
+ import { T as TCloudConfig, a as TCloudClient, a3 as SpendAuth } from './client-CaPP4njg.js';
3
3
  import '@tangle-network/sandbox';
4
4
 
5
5
  /**
package/dist/shielded.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  estimateCost,
4
4
  generateWallet,
5
5
  signSpendAuth
6
- } from "./chunk-THOMQXU5.js";
7
- import "./chunk-U4VOGRVW.js";
6
+ } from "./chunk-26M4HGWE.js";
7
+ import "./chunk-LUJXMUH5.js";
8
8
  export {
9
9
  createShieldedClient,
10
10
  estimateCost,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tangle-network/tcloud",
3
- "version": "0.4.12",
4
- "description": "TypeScript SDK and CLI for Tangle AI Cloud decentralized LLM inference",
3
+ "version": "0.4.14",
4
+ "description": "TypeScript SDK and CLI for Tangle Router, Sandbox, model routing, and agent service calls",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -71,7 +71,7 @@
71
71
  "dependencies": {
72
72
  "@scure/bip32": "^2.2.0",
73
73
  "@scure/bip39": "^2.2.0",
74
- "@tangle-network/sandbox": "^0.3.0",
74
+ "@tangle-network/sandbox": "^0.9.5",
75
75
  "commander": "^14.0.3",
76
76
  "viem": "^2.48.4",
77
77
  "@tangle-network/tcloud-attestation": "^0.1.1"
@@ -95,24 +95,29 @@
95
95
  "url": "git+https://github.com/tangle-network/tcloud.git",
96
96
  "directory": "packages/tcloud"
97
97
  },
98
- "homepage": "https://docs.tangleai.cloud",
98
+ "homepage": "https://router.tangle.tools/docs",
99
99
  "keywords": [
100
100
  "tangle",
101
101
  "ai",
102
102
  "llm",
103
103
  "inference",
104
104
  "decentralized",
105
+ "agent-runtime",
106
+ "sandbox",
107
+ "browser-agent",
108
+ "x402",
105
109
  "openai",
106
110
  "sdk",
107
111
  "cli",
108
112
  "privacy",
109
- "shielded-credits"
113
+ "shielded-credits",
114
+ "tangle-router"
110
115
  ],
111
116
  "engines": {
112
117
  "node": ">=18"
113
118
  },
114
119
  "scripts": {
115
- "build": "tsup src/index.ts src/cli.ts src/shielded.ts src/instance.ts src/attestation.ts src/sandbox.ts --format esm,cjs --dts --clean --external socks-proxy-agent",
120
+ "build": "tsup src/index.ts src/cli.ts src/mcp.ts src/shielded.ts src/instance.ts src/attestation.ts src/sandbox.ts --format esm,cjs --dts --clean --external socks-proxy-agent",
116
121
  "docs": "typedoc src/index.ts --out docs --name tcloud --readme README.md",
117
122
  "test": "vitest run",
118
123
  "test:e2e": "vitest run --config vitest.e2e.config.ts",