clawcompany 0.2.0 → 0.3.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.js +236 -39
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { join } from "path";
|
|
|
14
14
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
15
15
|
function banner() {
|
|
16
16
|
console.log("");
|
|
17
|
-
console.log(" \u{1F99E} ClawCompany v0.
|
|
17
|
+
console.log(" \u{1F99E} ClawCompany v0.3.0");
|
|
18
18
|
console.log(" Build for OPC. Every human being is a chairman.");
|
|
19
19
|
console.log("");
|
|
20
20
|
}
|
|
@@ -205,7 +205,7 @@ COST AWARENESS:
|
|
|
205
205
|
budgetTier: "earn",
|
|
206
206
|
budgetMonthly: null,
|
|
207
207
|
maxTokensPerTask: null,
|
|
208
|
-
tools: ["http", "filesystem"],
|
|
208
|
+
tools: ["http", "filesystem", "web_fetch", "web_search"],
|
|
209
209
|
skills: [],
|
|
210
210
|
isBuiltin: true,
|
|
211
211
|
isActive: true,
|
|
@@ -276,7 +276,7 @@ Own marketing strategy, content creation, brand voice, growth initiatives. Write
|
|
|
276
276
|
budgetTier: "earn",
|
|
277
277
|
budgetMonthly: null,
|
|
278
278
|
maxTokensPerTask: null,
|
|
279
|
-
tools: ["http", "filesystem"],
|
|
279
|
+
tools: ["http", "filesystem", "web_fetch", "web_search"],
|
|
280
280
|
skills: [],
|
|
281
281
|
isBuiltin: true,
|
|
282
282
|
isActive: true,
|
|
@@ -300,7 +300,7 @@ Conduct deep research \u2014 gather information, evaluate sources, analyze compe
|
|
|
300
300
|
budgetTier: "earn",
|
|
301
301
|
budgetMonthly: null,
|
|
302
302
|
maxTokensPerTask: null,
|
|
303
|
-
tools: ["http", "filesystem"],
|
|
303
|
+
tools: ["http", "filesystem", "web_fetch", "web_search"],
|
|
304
304
|
skills: [],
|
|
305
305
|
isBuiltin: true,
|
|
306
306
|
isActive: true,
|
|
@@ -315,7 +315,7 @@ Conduct deep research \u2014 gather information, evaluate sources, analyze compe
|
|
|
315
315
|
systemPrompt: `You are an Analyst. You report to the CFO or CEO.
|
|
316
316
|
|
|
317
317
|
Analyze data, detect patterns, calculate metrics, build models. Show calculations step by step. Present findings in tables. State assumptions. Quantify confidence levels.`,
|
|
318
|
-
model: "
|
|
318
|
+
model: "gpt-5-mini",
|
|
319
319
|
provider: "clawapi",
|
|
320
320
|
reportsTo: "cfo",
|
|
321
321
|
canDelegateTo: ["worker"],
|
|
@@ -323,7 +323,7 @@ Analyze data, detect patterns, calculate metrics, build models. Show calculation
|
|
|
323
323
|
budgetTier: "save",
|
|
324
324
|
budgetMonthly: null,
|
|
325
325
|
maxTokensPerTask: null,
|
|
326
|
-
tools: ["http", "filesystem", "code_interpreter"],
|
|
326
|
+
tools: ["http", "filesystem", "code_interpreter", "web_fetch", "web_search"],
|
|
327
327
|
skills: [],
|
|
328
328
|
isBuiltin: true,
|
|
329
329
|
isActive: true,
|
|
@@ -391,7 +391,7 @@ Prepare briefings, format reports, summarize documents, organize information. Ma
|
|
|
391
391
|
budgetTier: "save",
|
|
392
392
|
budgetMonthly: null,
|
|
393
393
|
maxTokensPerTask: null,
|
|
394
|
-
tools: ["filesystem", "http"],
|
|
394
|
+
tools: ["filesystem", "http", "web_fetch", "web_search"],
|
|
395
395
|
skills: [],
|
|
396
396
|
isBuiltin: true,
|
|
397
397
|
isActive: true,
|
|
@@ -1248,8 +1248,7 @@ var OpenAICompatibleProvider = class _OpenAICompatibleProvider {
|
|
|
1248
1248
|
// reasoning model timeout → fast model
|
|
1249
1249
|
"gpt-5.4": "claude-sonnet-4-6",
|
|
1250
1250
|
// GPT timeout → Sonnet
|
|
1251
|
-
"claude-opus-4-6": "claude-sonnet-4-6"
|
|
1252
|
-
"claude-sonnet-4-6": "gemini-3.1-flash-lite"
|
|
1251
|
+
"claude-opus-4-6": "claude-sonnet-4-6"
|
|
1253
1252
|
// Opus timeout → Sonnet
|
|
1254
1253
|
};
|
|
1255
1254
|
async chat(params) {
|
|
@@ -1270,11 +1269,14 @@ var OpenAICompatibleProvider = class _OpenAICompatibleProvider {
|
|
|
1270
1269
|
const url = `${this.baseUrl}/chat/completions`;
|
|
1271
1270
|
const body = {
|
|
1272
1271
|
model: params.model,
|
|
1273
|
-
messages: params.messages,
|
|
1272
|
+
messages: this.toApiMessages(params.messages),
|
|
1274
1273
|
temperature: params.temperature ?? 0.7,
|
|
1275
1274
|
max_tokens: params.maxTokens ?? 4096,
|
|
1276
|
-
stream:
|
|
1275
|
+
stream: true
|
|
1277
1276
|
};
|
|
1277
|
+
if (this.isReasoningModel(params.model)) {
|
|
1278
|
+
delete body.temperature;
|
|
1279
|
+
}
|
|
1278
1280
|
if (params.tools?.length) {
|
|
1279
1281
|
body.tools = params.tools;
|
|
1280
1282
|
}
|
|
@@ -1294,25 +1296,88 @@ var OpenAICompatibleProvider = class _OpenAICompatibleProvider {
|
|
|
1294
1296
|
this.id
|
|
1295
1297
|
);
|
|
1296
1298
|
}
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
+
let content = "";
|
|
1300
|
+
let model = params.model;
|
|
1301
|
+
let finishReason = "stop";
|
|
1302
|
+
let promptTokens = 0;
|
|
1303
|
+
let completionTokens = 0;
|
|
1304
|
+
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
1305
|
+
const reader = response.body.getReader();
|
|
1306
|
+
const decoder = new TextDecoder();
|
|
1307
|
+
let buffer = "";
|
|
1308
|
+
while (true) {
|
|
1309
|
+
const { done, value } = await reader.read();
|
|
1310
|
+
if (done) break;
|
|
1311
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1312
|
+
const lines = buffer.split("\n");
|
|
1313
|
+
buffer = lines.pop() ?? "";
|
|
1314
|
+
for (const line of lines) {
|
|
1315
|
+
if (!line.startsWith("data: ") || line === "data: [DONE]") continue;
|
|
1316
|
+
try {
|
|
1317
|
+
const chunk = JSON.parse(line.slice(6));
|
|
1318
|
+
const delta = chunk.choices?.[0]?.delta;
|
|
1319
|
+
if (delta?.content) content += delta.content;
|
|
1320
|
+
if (chunk.model) model = chunk.model;
|
|
1321
|
+
const fr = chunk.choices?.[0]?.finish_reason;
|
|
1322
|
+
if (fr) finishReason = fr;
|
|
1323
|
+
if (delta?.tool_calls) {
|
|
1324
|
+
for (const tc of delta.tool_calls) {
|
|
1325
|
+
const idx = tc.index ?? 0;
|
|
1326
|
+
if (!toolCallBuffers.has(idx)) {
|
|
1327
|
+
toolCallBuffers.set(idx, { id: tc.id ?? `call_${idx}`, name: "", args: "" });
|
|
1328
|
+
}
|
|
1329
|
+
const buf = toolCallBuffers.get(idx);
|
|
1330
|
+
if (tc.id) buf.id = tc.id;
|
|
1331
|
+
if (tc.function?.name) buf.name = tc.function.name;
|
|
1332
|
+
if (tc.function?.arguments) buf.args += tc.function.arguments;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
if (chunk.usage) {
|
|
1336
|
+
promptTokens = chunk.usage.prompt_tokens ?? 0;
|
|
1337
|
+
completionTokens = chunk.usage.completion_tokens ?? 0;
|
|
1338
|
+
}
|
|
1339
|
+
} catch {
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
const toolCalls = [];
|
|
1344
|
+
for (const [, buf] of [...toolCallBuffers.entries()].sort((a, b) => a[0] - b[0])) {
|
|
1345
|
+
toolCalls.push({ id: buf.id, type: "function", function: { name: buf.name, arguments: buf.args } });
|
|
1346
|
+
}
|
|
1299
1347
|
return {
|
|
1300
|
-
content
|
|
1301
|
-
model
|
|
1348
|
+
content,
|
|
1349
|
+
model,
|
|
1302
1350
|
provider: this.id,
|
|
1303
1351
|
usage: {
|
|
1304
|
-
inputTokens:
|
|
1305
|
-
outputTokens:
|
|
1306
|
-
cost: calculateCost(
|
|
1307
|
-
params.model,
|
|
1308
|
-
data.usage?.prompt_tokens ?? 0,
|
|
1309
|
-
data.usage?.completion_tokens ?? 0
|
|
1310
|
-
)
|
|
1352
|
+
inputTokens: promptTokens,
|
|
1353
|
+
outputTokens: completionTokens,
|
|
1354
|
+
cost: calculateCost(params.model, promptTokens, completionTokens)
|
|
1311
1355
|
},
|
|
1312
|
-
toolCalls:
|
|
1313
|
-
finishReason
|
|
1356
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
1357
|
+
finishReason
|
|
1314
1358
|
};
|
|
1315
1359
|
}
|
|
1360
|
+
/** Convert internal message format to OpenAI API format */
|
|
1361
|
+
toApiMessages(messages) {
|
|
1362
|
+
return messages.map((msg) => {
|
|
1363
|
+
const out = {
|
|
1364
|
+
role: msg.role,
|
|
1365
|
+
content: msg.content
|
|
1366
|
+
};
|
|
1367
|
+
if (msg.toolCalls) {
|
|
1368
|
+
out.tool_calls = msg.toolCalls;
|
|
1369
|
+
if (!out.content) out.content = null;
|
|
1370
|
+
}
|
|
1371
|
+
if (msg.role === "tool" && msg.toolCallId) {
|
|
1372
|
+
out.tool_call_id = msg.toolCallId;
|
|
1373
|
+
}
|
|
1374
|
+
if (msg.name) out.name = msg.name;
|
|
1375
|
+
return out;
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
isReasoningModel(model) {
|
|
1379
|
+
return /^(o1|o3|gpt-5-mini)/.test(model);
|
|
1380
|
+
}
|
|
1316
1381
|
async listModels() {
|
|
1317
1382
|
if (Array.isArray(this.config.models)) {
|
|
1318
1383
|
return this.config.models;
|
|
@@ -1588,6 +1653,10 @@ var ToolExecutor = class {
|
|
|
1588
1653
|
return this.execHttp(args);
|
|
1589
1654
|
case "code_interpreter":
|
|
1590
1655
|
return this.execCode(args);
|
|
1656
|
+
case "web_fetch":
|
|
1657
|
+
return this.execWebFetch(args);
|
|
1658
|
+
case "web_search":
|
|
1659
|
+
return this.execWebSearch(args);
|
|
1591
1660
|
default:
|
|
1592
1661
|
return `Unknown tool: ${toolName}`;
|
|
1593
1662
|
}
|
|
@@ -1648,6 +1717,88 @@ ${text.slice(0, 5e3)}`;
|
|
|
1648
1717
|
}
|
|
1649
1718
|
return `Unsupported language: ${language}`;
|
|
1650
1719
|
}
|
|
1720
|
+
async execWebFetch(args) {
|
|
1721
|
+
const { url, maxLength } = args;
|
|
1722
|
+
const limit = maxLength ?? 8e3;
|
|
1723
|
+
try {
|
|
1724
|
+
const response = await fetch(url, {
|
|
1725
|
+
headers: {
|
|
1726
|
+
"User-Agent": "ClawCompany/1.0 (AI Agent)",
|
|
1727
|
+
"Accept": "text/html,application/xhtml+xml,text/plain,application/json"
|
|
1728
|
+
},
|
|
1729
|
+
redirect: "follow",
|
|
1730
|
+
signal: AbortSignal.timeout(15e3)
|
|
1731
|
+
});
|
|
1732
|
+
if (!response.ok) {
|
|
1733
|
+
return `Error: HTTP ${response.status} ${response.statusText}`;
|
|
1734
|
+
}
|
|
1735
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
1736
|
+
const raw = await response.text();
|
|
1737
|
+
if (contentType.includes("application/json")) {
|
|
1738
|
+
return raw.slice(0, limit);
|
|
1739
|
+
}
|
|
1740
|
+
if (contentType.includes("text/html")) {
|
|
1741
|
+
const text = raw.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, "").replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, "").replace(/<header[^>]*>[\s\S]*?<\/header>/gi, "").replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\s+/g, " ").trim();
|
|
1742
|
+
return text.slice(0, limit);
|
|
1743
|
+
}
|
|
1744
|
+
return raw.slice(0, limit);
|
|
1745
|
+
} catch (err) {
|
|
1746
|
+
if (err.name === "TimeoutError") return "Error: Request timed out (15s)";
|
|
1747
|
+
return `Error: ${err.message}`;
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
async execWebSearch(args) {
|
|
1751
|
+
const { query, maxResults } = args;
|
|
1752
|
+
const limit = Math.min(maxResults ?? 5, 10);
|
|
1753
|
+
try {
|
|
1754
|
+
const encoded = encodeURIComponent(query);
|
|
1755
|
+
const response = await fetch(`https://html.duckduckgo.com/html/?q=${encoded}`, {
|
|
1756
|
+
headers: {
|
|
1757
|
+
"User-Agent": "ClawCompany/1.0 (AI Agent)"
|
|
1758
|
+
},
|
|
1759
|
+
signal: AbortSignal.timeout(1e4)
|
|
1760
|
+
});
|
|
1761
|
+
if (!response.ok) {
|
|
1762
|
+
return `Error: Search failed with HTTP ${response.status}`;
|
|
1763
|
+
}
|
|
1764
|
+
const html = await response.text();
|
|
1765
|
+
const results = [];
|
|
1766
|
+
const resultBlocks = html.split('class="result__body"');
|
|
1767
|
+
for (let i = 1; i < resultBlocks.length && results.length < limit; i++) {
|
|
1768
|
+
const block = resultBlocks[i];
|
|
1769
|
+
const titleMatch = block.match(/class="result__a"[^>]*>([^<]+)</);
|
|
1770
|
+
const title = titleMatch?.[1]?.trim() ?? "";
|
|
1771
|
+
const urlMatch = block.match(/href="\/\/duckduckgo\.com\/l\/\?[^"]*uddg=([^&"]+)/);
|
|
1772
|
+
const url = urlMatch?.[1] ? decodeURIComponent(urlMatch[1]) : "";
|
|
1773
|
+
const snippetMatch = block.match(/class="result__snippet"[^>]*>([\s\S]*?)<\/a>/);
|
|
1774
|
+
const snippet = snippetMatch?.[1]?.replace(/<[^>]+>/g, "")?.replace(/\s+/g, " ")?.trim() ?? "";
|
|
1775
|
+
if (title && url) {
|
|
1776
|
+
results.push({ title, url, snippet });
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
if (results.length === 0) {
|
|
1780
|
+
return `No results found for "${query}"`;
|
|
1781
|
+
}
|
|
1782
|
+
let output = `Search results for "${query}":
|
|
1783
|
+
|
|
1784
|
+
`;
|
|
1785
|
+
for (let i = 0; i < results.length; i++) {
|
|
1786
|
+
output += `${i + 1}. ${results[i].title}
|
|
1787
|
+
`;
|
|
1788
|
+
output += ` URL: ${results[i].url}
|
|
1789
|
+
`;
|
|
1790
|
+
if (results[i].snippet) {
|
|
1791
|
+
output += ` ${results[i].snippet}
|
|
1792
|
+
`;
|
|
1793
|
+
}
|
|
1794
|
+
output += "\n";
|
|
1795
|
+
}
|
|
1796
|
+
return output;
|
|
1797
|
+
} catch (err) {
|
|
1798
|
+
if (err.name === "TimeoutError") return "Error: Search timed out (10s)";
|
|
1799
|
+
return `Error: ${err.message}`;
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1651
1802
|
};
|
|
1652
1803
|
|
|
1653
1804
|
// ../packages/tools/src/index.ts
|
|
@@ -1714,6 +1865,36 @@ var BUILTIN_TOOLS = {
|
|
|
1714
1865
|
required: ["language", "code"]
|
|
1715
1866
|
}
|
|
1716
1867
|
}
|
|
1868
|
+
},
|
|
1869
|
+
web_fetch: {
|
|
1870
|
+
type: "function",
|
|
1871
|
+
function: {
|
|
1872
|
+
name: "web_fetch",
|
|
1873
|
+
description: "Fetch a web page and extract its text content. Use this to read articles, documentation, blog posts, or any public web page. Returns cleaned text without HTML tags.",
|
|
1874
|
+
parameters: {
|
|
1875
|
+
type: "object",
|
|
1876
|
+
properties: {
|
|
1877
|
+
url: { type: "string", description: "URL of the web page to fetch" },
|
|
1878
|
+
maxLength: { type: "number", description: "Max characters to return (default: 8000)" }
|
|
1879
|
+
},
|
|
1880
|
+
required: ["url"]
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
},
|
|
1884
|
+
web_search: {
|
|
1885
|
+
type: "function",
|
|
1886
|
+
function: {
|
|
1887
|
+
name: "web_search",
|
|
1888
|
+
description: "Search the web for current information. Returns a list of results with titles, URLs, and snippets. Use this to find up-to-date facts, news, prices, or research topics.",
|
|
1889
|
+
parameters: {
|
|
1890
|
+
type: "object",
|
|
1891
|
+
properties: {
|
|
1892
|
+
query: { type: "string", description: "Search query" },
|
|
1893
|
+
maxResults: { type: "number", description: "Max results to return (default: 5, max: 10)" }
|
|
1894
|
+
},
|
|
1895
|
+
required: ["query"]
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1717
1898
|
}
|
|
1718
1899
|
};
|
|
1719
1900
|
function getToolsForRole(toolNames) {
|
|
@@ -1739,7 +1920,7 @@ var AgentExecutor = class {
|
|
|
1739
1920
|
content: this.buildTaskPrompt(task)
|
|
1740
1921
|
}
|
|
1741
1922
|
];
|
|
1742
|
-
const MAX_TURNS =
|
|
1923
|
+
const MAX_TURNS = 15;
|
|
1743
1924
|
for (let turn = 0; turn < MAX_TURNS; turn++) {
|
|
1744
1925
|
const response = await this.router.chatAsRole(
|
|
1745
1926
|
role2.id,
|
|
@@ -1951,24 +2132,40 @@ ${truncated}
|
|
|
1951
2132
|
`;
|
|
1952
2133
|
}
|
|
1953
2134
|
}
|
|
1954
|
-
const
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
2135
|
+
const role2 = this.router.getRole(ws.assignTo);
|
|
2136
|
+
if (!role2) throw new Error(`Role "${ws.assignTo}" not found`);
|
|
2137
|
+
const result = await this.executor.execute(role2, {
|
|
2138
|
+
id: ws.id,
|
|
2139
|
+
companyId: "default",
|
|
2140
|
+
missionId: ws.missionId,
|
|
2141
|
+
workStreamId: ws.id,
|
|
2142
|
+
title: ws.title,
|
|
2143
|
+
description: `${ws.description}
|
|
1960
2144
|
|
|
1961
2145
|
Complexity: ${ws.estimatedComplexity}${context}
|
|
1962
2146
|
|
|
1963
|
-
Today's date is ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
1964
|
-
|
|
1965
|
-
|
|
2147
|
+
Today's date is ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.`,
|
|
2148
|
+
assignedTo: ws.assignTo,
|
|
2149
|
+
createdBy: "ceo",
|
|
2150
|
+
reportTo: "ceo",
|
|
2151
|
+
status: "in_progress",
|
|
2152
|
+
priority: 1,
|
|
2153
|
+
tokensIn: 0,
|
|
2154
|
+
tokensOut: 0,
|
|
2155
|
+
cost: 0,
|
|
2156
|
+
modelUsed: role2.model,
|
|
2157
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2158
|
+
});
|
|
2159
|
+
if (result.toolCallCount > 0) {
|
|
2160
|
+
console.log(` \u{1F527} ${result.toolCallCount} tool calls executed`);
|
|
2161
|
+
}
|
|
1966
2162
|
return {
|
|
1967
|
-
content:
|
|
1968
|
-
cost:
|
|
1969
|
-
tokensIn:
|
|
1970
|
-
tokensOut:
|
|
1971
|
-
model:
|
|
2163
|
+
content: result.output,
|
|
2164
|
+
cost: result.cost,
|
|
2165
|
+
tokensIn: result.tokensIn,
|
|
2166
|
+
tokensOut: result.tokensOut,
|
|
2167
|
+
model: result.modelUsed,
|
|
2168
|
+
toolCallCount: result.toolCallCount
|
|
1972
2169
|
};
|
|
1973
2170
|
}
|
|
1974
2171
|
topologicalSort(workStreams) {
|
package/package.json
CHANGED