@clawos-dev/clawd 0.2.679 → 0.2.680
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/cli.cjs +8 -5
- package/dist/rpc-tool/mcp-server.cjs +68 -11
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -57210,7 +57210,8 @@ function writeRpcToolMcpConfig(args) {
|
|
|
57210
57210
|
}
|
|
57211
57211
|
};
|
|
57212
57212
|
import_node_fs33.default.mkdirSync(args.dataDir, { recursive: true });
|
|
57213
|
-
import_node_fs33.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
57213
|
+
import_node_fs33.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), { encoding: "utf8", mode: 384 });
|
|
57214
|
+
import_node_fs33.default.chmodSync(cfgPath, 384);
|
|
57214
57215
|
return cfgPath;
|
|
57215
57216
|
}
|
|
57216
57217
|
|
|
@@ -75335,7 +75336,7 @@ function computeMethodAccess(args) {
|
|
|
75335
75336
|
}
|
|
75336
75337
|
|
|
75337
75338
|
// src/version.ts
|
|
75338
|
-
var version = "0.2.
|
|
75339
|
+
var version = "0.2.680".length > 0 ? "0.2.680" : "dev";
|
|
75339
75340
|
|
|
75340
75341
|
// src/cli-probe/probe.ts
|
|
75341
75342
|
var fs86 = __toESM(require("fs"), 1);
|
|
@@ -75418,9 +75419,11 @@ function buildReadyFrame(deps, client) {
|
|
|
75418
75419
|
};
|
|
75419
75420
|
}
|
|
75420
75421
|
function buildMetaHandlers(deps) {
|
|
75421
|
-
const info = async () =>
|
|
75422
|
-
|
|
75423
|
-
|
|
75422
|
+
const info = async (_frame, client) => {
|
|
75423
|
+
const frame = buildReadyFrame(deps);
|
|
75424
|
+
if (client.transport === "http") delete frame.httpToken;
|
|
75425
|
+
return { response: { type: "info", ...frame } };
|
|
75426
|
+
};
|
|
75424
75427
|
const ping = async () => ({
|
|
75425
75428
|
response: { type: "pong", at: Date.now() }
|
|
75426
75429
|
});
|
|
@@ -21125,6 +21125,17 @@ function log(msg, extra) {
|
|
|
21125
21125
|
} catch {
|
|
21126
21126
|
}
|
|
21127
21127
|
}
|
|
21128
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
21129
|
+
var DEFAULT_MAX_RESULT_CHARS = 6e4;
|
|
21130
|
+
function positiveIntFromEnv(name, fallback) {
|
|
21131
|
+
const n = Number(process.env[name]);
|
|
21132
|
+
return Number.isInteger(n) && n > 0 ? n : fallback;
|
|
21133
|
+
}
|
|
21134
|
+
function truncateResult(text, max) {
|
|
21135
|
+
if (max === void 0 || text.length <= max) return text;
|
|
21136
|
+
return text.slice(0, max) + `
|
|
21137
|
+
\u2026[truncated: ${text.length - max} of ${text.length} chars omitted. Narrow the call: pass \`slim:true\` to history:read, or use limit/offset/cursor where the method supports them.]`;
|
|
21138
|
+
}
|
|
21128
21139
|
async function handleCallToolCall(input, ctx) {
|
|
21129
21140
|
const f = ctx.fetch ?? fetch;
|
|
21130
21141
|
const args = input.args ?? {};
|
|
@@ -21142,9 +21153,23 @@ async function handleCallToolCall(input, ctx) {
|
|
|
21142
21153
|
"content-type": "application/json",
|
|
21143
21154
|
authorization: `Bearer ${ctx.daemonToken}`
|
|
21144
21155
|
},
|
|
21145
|
-
body: JSON.stringify(body)
|
|
21156
|
+
body: JSON.stringify(body),
|
|
21157
|
+
signal: AbortSignal.timeout(ctx.timeoutMs ?? DEFAULT_TIMEOUT_MS)
|
|
21146
21158
|
});
|
|
21147
21159
|
} catch (err) {
|
|
21160
|
+
if (err instanceof Error && err.name === "TimeoutError") {
|
|
21161
|
+
const secs = Math.round((ctx.timeoutMs ?? DEFAULT_TIMEOUT_MS) / 1e3);
|
|
21162
|
+
log("call timed out", { url, secs });
|
|
21163
|
+
return {
|
|
21164
|
+
content: [
|
|
21165
|
+
{
|
|
21166
|
+
type: "text",
|
|
21167
|
+
text: `RPC timed out after ${secs}s waiting for ${input.method}. The daemon may still be running it \u2014 check the result before retrying a method that writes.`
|
|
21168
|
+
}
|
|
21169
|
+
],
|
|
21170
|
+
isError: true
|
|
21171
|
+
};
|
|
21172
|
+
}
|
|
21148
21173
|
const msg = err instanceof Error ? err.message : String(err);
|
|
21149
21174
|
log("call fetch threw", { url, msg });
|
|
21150
21175
|
return {
|
|
@@ -21170,9 +21195,27 @@ async function handleCallToolCall(input, ctx) {
|
|
|
21170
21195
|
};
|
|
21171
21196
|
}
|
|
21172
21197
|
log("call ok", { url });
|
|
21173
|
-
return { content: [{ type: "text", text: JSON.stringify(json.result) }] };
|
|
21198
|
+
return { content: [{ type: "text", text: truncateResult(JSON.stringify(json.result), ctx.maxResultChars) }] };
|
|
21174
21199
|
}
|
|
21175
|
-
|
|
21200
|
+
var SUMMARY_MAX_CHARS = 100;
|
|
21201
|
+
function summarize(description) {
|
|
21202
|
+
const end = description.search(/。|\. |\n/);
|
|
21203
|
+
const first = end === -1 ? description : description.slice(0, end + (description[end] === "." ? 1 : 0));
|
|
21204
|
+
return first.length > SUMMARY_MAX_CHARS ? first.slice(0, SUMMARY_MAX_CHARS) + "\u2026" : first;
|
|
21205
|
+
}
|
|
21206
|
+
async function handleListToolCall(callerCtx, opts = {}) {
|
|
21207
|
+
const ctx = { ...callerCtx, maxResultChars: void 0 };
|
|
21208
|
+
if (opts.method) {
|
|
21209
|
+
const one = await handleCallToolCall({ method: "meta:methods", args: { method: opts.method } }, ctx);
|
|
21210
|
+
if (one.isError) return one;
|
|
21211
|
+
try {
|
|
21212
|
+
const entry = JSON.parse(one.content[0].text).methods[0];
|
|
21213
|
+
if (!entry) throw new Error("empty");
|
|
21214
|
+
return { content: [{ type: "text", text: JSON.stringify(entry, null, 2) }] };
|
|
21215
|
+
} catch {
|
|
21216
|
+
return { content: [{ type: "text", text: "meta:methods returned an unexpected shape" }], isError: true };
|
|
21217
|
+
}
|
|
21218
|
+
}
|
|
21176
21219
|
const raw = await handleCallToolCall({ method: "meta:methods" }, ctx);
|
|
21177
21220
|
if (raw.isError) return raw;
|
|
21178
21221
|
let methods;
|
|
@@ -21181,6 +21224,13 @@ async function handleListToolCall(ctx) {
|
|
|
21181
21224
|
} catch {
|
|
21182
21225
|
return { content: [{ type: "text", text: "meta:methods returned an unexpected shape" }], isError: true };
|
|
21183
21226
|
}
|
|
21227
|
+
if (opts.prefix) {
|
|
21228
|
+
const prefix = opts.prefix;
|
|
21229
|
+
methods = methods.filter((m) => m.name.startsWith(prefix));
|
|
21230
|
+
if (methods.length === 0) {
|
|
21231
|
+
return { content: [{ type: "text", text: `No methods start with "${prefix}". Call list with no arguments to see all.` }] };
|
|
21232
|
+
}
|
|
21233
|
+
}
|
|
21184
21234
|
return { content: [{ type: "text", text: formatMethodList(methods) }] };
|
|
21185
21235
|
}
|
|
21186
21236
|
function formatMethodList(methods) {
|
|
@@ -21199,7 +21249,7 @@ function formatMethodList(methods) {
|
|
|
21199
21249
|
for (const [reason, group2] of byReason) {
|
|
21200
21250
|
if (reason) lines.push(`(${reason})`);
|
|
21201
21251
|
for (const m of group2) {
|
|
21202
|
-
lines.push(m.description ? `- ${m.name} \u2014 ${m.description}` : `- ${m.name}`);
|
|
21252
|
+
lines.push(m.description ? `- ${m.name} \u2014 ${summarize(m.description)}` : `- ${m.name}`);
|
|
21203
21253
|
if (m.args && m.args.length > 0) {
|
|
21204
21254
|
lines.push(` args: ${m.args.map((a) => a.required ? `${a.name}*` : a.name).join(", ")}`);
|
|
21205
21255
|
} else if (m.args === null) {
|
|
@@ -21211,35 +21261,42 @@ function formatMethodList(methods) {
|
|
|
21211
21261
|
}
|
|
21212
21262
|
lines.push("");
|
|
21213
21263
|
}
|
|
21214
|
-
lines.push(
|
|
21264
|
+
lines.push(
|
|
21265
|
+
"Call any of these with the `call` tool: call({ method, args }). `*` marks required args. Descriptions are shortened here: list({ method }) returns one method in full with its args schema."
|
|
21266
|
+
);
|
|
21215
21267
|
return lines.join("\n");
|
|
21216
21268
|
}
|
|
21217
21269
|
async function main() {
|
|
21218
21270
|
const daemonUrl = process.env.CLAWD_DAEMON_URL;
|
|
21219
21271
|
const daemonToken = process.env.CLAWD_DAEMON_TOKEN;
|
|
21220
21272
|
const sessionId = process.env.CLAWD_SESSION_ID;
|
|
21221
|
-
|
|
21273
|
+
const timeoutMs = positiveIntFromEnv("CLAWD_RPC_TIMEOUT_MS", DEFAULT_TIMEOUT_MS);
|
|
21274
|
+
const maxResultChars = positiveIntFromEnv("CLAWD_RPC_MAX_RESULT_CHARS", DEFAULT_MAX_RESULT_CHARS);
|
|
21275
|
+
log("boot", { pid: process.pid, hasSessionId: Boolean(sessionId), logPath: RPC_LOG ?? "(stderr)", timeoutMs, maxResultChars });
|
|
21222
21276
|
const server = new McpServer({ name: "clawd-rpc", version: "0.1.0" });
|
|
21223
21277
|
server.registerTool(
|
|
21224
21278
|
"call",
|
|
21225
21279
|
{
|
|
21226
21280
|
title: "Call a clawd daemon RPC method",
|
|
21227
|
-
description: 'Call a clawd daemon RPC method over the authenticated local channel. `method` is the canonical method name (e.g. "attachment.signUrl", "persona:list", "session:list"); `args` is the JSON body for that method. sessionId is auto-filled from this session unless explicitly provided in args. The daemon is the sole authority on method existence and authorization \u2014 unknown methods or missing permissions surface as errors from the daemon.',
|
|
21281
|
+
description: 'Call a clawd daemon RPC method over the authenticated local channel. `method` is the canonical method name (e.g. "attachment.signUrl", "persona:list", "session:list"); `args` is the JSON body for that method. sessionId is auto-filled from this session unless explicitly provided in args. The daemon is the sole authority on method existence and authorization \u2014 unknown methods or missing permissions surface as errors from the daemon. Gives up after the timeout, and long results are truncated with a hint to narrow the call.',
|
|
21228
21282
|
inputSchema: {
|
|
21229
21283
|
method: external_exports.string().min(1).describe('canonical RPC method name, e.g. "persona:list"'),
|
|
21230
21284
|
args: external_exports.record(external_exports.unknown()).optional().describe("JSON arguments for the method")
|
|
21231
21285
|
}
|
|
21232
21286
|
},
|
|
21233
|
-
async (input) => handleCallToolCall(input, { daemonUrl, daemonToken, sessionId })
|
|
21287
|
+
async (input) => handleCallToolCall(input, { daemonUrl, daemonToken, sessionId, timeoutMs, maxResultChars })
|
|
21234
21288
|
);
|
|
21235
21289
|
server.registerTool(
|
|
21236
21290
|
"list",
|
|
21237
21291
|
{
|
|
21238
21292
|
title: "List callable clawd daemon RPC methods",
|
|
21239
|
-
description:
|
|
21240
|
-
inputSchema: {
|
|
21293
|
+
description: 'List the RPC methods this daemon exposes, grouped by whether THIS connection can call it, one shortened line per method. The daemon has 100+ methods and `call` does no local validation, so prefer `prefix` (e.g. "session:") to narrow the list, and `method` to get one method in full with its args schema. With no arguments it lists everything.',
|
|
21294
|
+
inputSchema: {
|
|
21295
|
+
prefix: external_exports.string().min(1).optional().describe('only methods whose name starts with this, e.g. "session:"'),
|
|
21296
|
+
method: external_exports.string().min(1).optional().describe("one exact method name: returns its full description and args schema")
|
|
21297
|
+
}
|
|
21241
21298
|
},
|
|
21242
|
-
async () => handleListToolCall({ daemonUrl, daemonToken, sessionId })
|
|
21299
|
+
async (input) => handleListToolCall({ daemonUrl, daemonToken, sessionId, timeoutMs }, input)
|
|
21243
21300
|
);
|
|
21244
21301
|
await server.connect(new StdioServerTransport());
|
|
21245
21302
|
}
|