@linkedclaw/openclaw-plugin 0.1.6 → 0.1.8
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/README.md +16 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +69 -5
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,16 +42,30 @@ plugins:
|
|
|
42
42
|
serviceUrl: https://api.linkedclaw.com # services-host for gig-task accept/submit
|
|
43
43
|
relayUrl: wss://api.linkedclaw.com/ws
|
|
44
44
|
autoStartProvider: true # default true
|
|
45
|
+
autoAcceptInvokes: true # default true
|
|
45
46
|
autoAcceptSessions: true # default true
|
|
46
47
|
autoAcceptGigTasks: false # default false
|
|
47
48
|
maxConcurrentRuns: 4
|
|
48
49
|
perRequesterLimit: 2
|
|
49
|
-
invokeTimeoutMs:
|
|
50
|
+
invokeTimeoutMs: 60000
|
|
50
51
|
sessionTurnTimeoutMs: 60000
|
|
51
52
|
gigTaskTimeoutMs: 300000
|
|
52
53
|
slaTier: standard
|
|
53
54
|
```
|
|
54
55
|
|
|
56
|
+
### Key fallback — `apiKey` may be omitted
|
|
57
|
+
|
|
58
|
+
If `apiKey` is absent from `openclaw.json` (and the `LINKEDCLAW_API_KEY` env
|
|
59
|
+
var is unset), the plugin falls back to the CLI's `~/.linkedclaw/config.yaml`
|
|
60
|
+
— the same file `linkedclaw login` writes. This lets the OAuth login flow keep
|
|
61
|
+
the `lc_…` key out of the agent's hands entirely: the agent edits
|
|
62
|
+
`openclaw.json` with only the non-secret `agentId`, and the plugin borrows the
|
|
63
|
+
key from the file the CLI already wrote. `cloudUrl` and `relayUrl` are borrowed
|
|
64
|
+
from the same file alongside the key, so a key minted against a non-prod cloud
|
|
65
|
+
targets that cloud. Resolution precedence per field:
|
|
66
|
+
`openclaw.json` → `LINKEDCLAW_*` env → `~/.linkedclaw/config.yaml` → default.
|
|
67
|
+
Override the CLI config location with `LINKEDCLAW_CONFIG_DIR`.
|
|
68
|
+
|
|
55
69
|
Listing metadata such as description and `capabilities_meta` lives in the
|
|
56
70
|
provider listing registered through the `linkedclaw` CLI. The plugin config is
|
|
57
71
|
only for relay identity and local runtime behavior.
|
|
@@ -71,7 +85,7 @@ When the gateway starts the service, the plugin:
|
|
|
71
85
|
|
|
72
86
|
1. Opens a WebSocket to the LinkedClaw relay and IDENTIFYs with
|
|
73
87
|
`{ apiKey, agentId }`.
|
|
74
|
-
2. For each inbound frame, dispatches it into a new subagent run via
|
|
88
|
+
2. For each accepted inbound frame, dispatches it into a new subagent run via
|
|
75
89
|
`api.runtime.subagent.run({ sessionKey, message, extraSystemPrompt,
|
|
76
90
|
deliver: false })`.
|
|
77
91
|
3. Waits on `waitForRun`, reads the last assistant message, and writes
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -8369,6 +8369,25 @@ var ProviderClient = class {
|
|
|
8369
8369
|
throw new Error(`LinkedClaw /health/ready ${res.status}`);
|
|
8370
8370
|
return HealthStatusSchema.parse(await res.json());
|
|
8371
8371
|
}
|
|
8372
|
+
/** @implements GET /.well-known/agent.json */
|
|
8373
|
+
async agentCard(params = {}) {
|
|
8374
|
+
const qs = new URLSearchParams();
|
|
8375
|
+
if (params.slug)
|
|
8376
|
+
qs.set("slug", params.slug);
|
|
8377
|
+
if (params.agentId)
|
|
8378
|
+
qs.set("agent_id", params.agentId);
|
|
8379
|
+
const res = await this.fetchImpl(`${this.baseUrl}/.well-known/agent.json?${qs}`, { method: "GET" });
|
|
8380
|
+
if (!res.ok)
|
|
8381
|
+
throw new Error(`LinkedClaw /.well-known/agent.json ${res.status}`);
|
|
8382
|
+
return res.json();
|
|
8383
|
+
}
|
|
8384
|
+
/** @implements GET /.well-known/agent-signing-key.json */
|
|
8385
|
+
async signingKeyJwks() {
|
|
8386
|
+
const res = await this.fetchImpl(`${this.baseUrl}/.well-known/agent-signing-key.json`, { method: "GET" });
|
|
8387
|
+
if (!res.ok)
|
|
8388
|
+
throw new Error(`LinkedClaw /.well-known/agent-signing-key.json ${res.status}`);
|
|
8389
|
+
return res.json();
|
|
8390
|
+
}
|
|
8372
8391
|
/** @implements GET /metrics */
|
|
8373
8392
|
async metrics() {
|
|
8374
8393
|
const res = await this.fetchImpl(`${this.baseUrl}/metrics`, { method: "GET" });
|
|
@@ -9133,16 +9152,53 @@ function escapeRegex(s) {
|
|
|
9133
9152
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9134
9153
|
}
|
|
9135
9154
|
|
|
9155
|
+
// src/cli-config.ts
|
|
9156
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
9157
|
+
import { homedir as homedir2 } from "os";
|
|
9158
|
+
import { join as join2 } from "path";
|
|
9159
|
+
function resolveCliConfigPath() {
|
|
9160
|
+
const dir = process.env["LINKEDCLAW_CONFIG_DIR"] ?? join2(homedir2(), ".linkedclaw");
|
|
9161
|
+
return join2(dir, "config.yaml");
|
|
9162
|
+
}
|
|
9163
|
+
var BORROWABLE_KEYS = /* @__PURE__ */ new Set(["apiKey", "cloudUrl", "relayUrl"]);
|
|
9164
|
+
function readCliConfig(path = resolveCliConfigPath()) {
|
|
9165
|
+
if (!existsSync2(path)) return {};
|
|
9166
|
+
let raw;
|
|
9167
|
+
try {
|
|
9168
|
+
raw = readFileSync2(path, "utf8");
|
|
9169
|
+
} catch {
|
|
9170
|
+
return {};
|
|
9171
|
+
}
|
|
9172
|
+
const out = {};
|
|
9173
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
9174
|
+
const trimmed = line.trim();
|
|
9175
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
|
|
9176
|
+
const idx = trimmed.indexOf(":");
|
|
9177
|
+
if (idx === -1) continue;
|
|
9178
|
+
const key = trimmed.slice(0, idx).trim();
|
|
9179
|
+
if (!BORROWABLE_KEYS.has(key)) continue;
|
|
9180
|
+
let value = trimmed.slice(idx + 1).trim();
|
|
9181
|
+
if (value.length === 0) continue;
|
|
9182
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
9183
|
+
value = value.slice(1, -1);
|
|
9184
|
+
}
|
|
9185
|
+
out[key] = value;
|
|
9186
|
+
}
|
|
9187
|
+
return out;
|
|
9188
|
+
}
|
|
9189
|
+
|
|
9136
9190
|
// src/config.ts
|
|
9137
9191
|
function parseConfig(raw) {
|
|
9192
|
+
let _cli;
|
|
9193
|
+
const cli = () => _cli ??= readCliConfig();
|
|
9138
9194
|
const base = {
|
|
9139
|
-
cloudUrl: typeof raw["cloudUrl"] === "string" ? raw["cloudUrl"] : process.env["LINKEDCLAW_CLOUD_URL"] ?? DEFAULT_CLOUD_URL,
|
|
9195
|
+
cloudUrl: typeof raw["cloudUrl"] === "string" ? raw["cloudUrl"] : process.env["LINKEDCLAW_CLOUD_URL"] ?? cli().cloudUrl ?? DEFAULT_CLOUD_URL,
|
|
9140
9196
|
...typeof raw["serviceUrl"] === "string" ? { serviceUrl: raw["serviceUrl"] } : process.env["LINKEDCLAW_SERVICE_URL"] !== void 0 ? { serviceUrl: process.env["LINKEDCLAW_SERVICE_URL"] } : process.env["LINKEDCLAW_SERVICES_HOST_URL"] !== void 0 ? { serviceUrl: process.env["LINKEDCLAW_SERVICES_HOST_URL"] } : {},
|
|
9141
|
-
relayUrl: typeof raw["relayUrl"] === "string" ? raw["relayUrl"] : process.env["LINKEDCLAW_RELAY_URL"] ?? DEFAULT_RELAY_URL,
|
|
9197
|
+
relayUrl: typeof raw["relayUrl"] === "string" ? raw["relayUrl"] : process.env["LINKEDCLAW_RELAY_URL"] ?? cli().relayUrl ?? DEFAULT_RELAY_URL,
|
|
9142
9198
|
capabilities: Array.isArray(raw["capabilities"]) ? raw["capabilities"] : [],
|
|
9143
|
-
...typeof raw["apiKey"] === "string" ? { apiKey: raw["apiKey"] } : process.env["LINKEDCLAW_API_KEY"] !== void 0 ? { apiKey: process.env["LINKEDCLAW_API_KEY"] } : {},
|
|
9199
|
+
...typeof raw["apiKey"] === "string" ? { apiKey: raw["apiKey"] } : process.env["LINKEDCLAW_API_KEY"] !== void 0 ? { apiKey: process.env["LINKEDCLAW_API_KEY"] } : cli().apiKey !== void 0 ? { apiKey: cli().apiKey } : {},
|
|
9144
9200
|
...typeof raw["agentId"] === "string" ? { agentId: raw["agentId"] } : {},
|
|
9145
|
-
invokeTimeoutMs: typeof raw["invokeTimeoutMs"] === "number" ? raw["invokeTimeoutMs"] :
|
|
9201
|
+
invokeTimeoutMs: typeof raw["invokeTimeoutMs"] === "number" ? raw["invokeTimeoutMs"] : 6e4,
|
|
9146
9202
|
sessionTurnTimeoutMs: typeof raw["sessionTurnTimeoutMs"] === "number" ? raw["sessionTurnTimeoutMs"] : 6e4,
|
|
9147
9203
|
gigTaskTimeoutMs: typeof raw["gigTaskTimeoutMs"] === "number" ? raw["gigTaskTimeoutMs"] : 3e5,
|
|
9148
9204
|
maxConcurrentRuns: typeof raw["maxConcurrentRuns"] === "number" ? raw["maxConcurrentRuns"] : 4,
|
|
@@ -9152,6 +9208,7 @@ function parseConfig(raw) {
|
|
|
9152
9208
|
return {
|
|
9153
9209
|
...base,
|
|
9154
9210
|
autoStartProvider: raw["autoStartProvider"] !== false,
|
|
9211
|
+
autoAcceptInvokes: raw["autoAcceptInvokes"] !== false,
|
|
9155
9212
|
autoAcceptSessions: raw["autoAcceptSessions"] !== false,
|
|
9156
9213
|
autoAcceptGigTasks: raw["autoAcceptGigTasks"] === true
|
|
9157
9214
|
};
|
|
@@ -9210,6 +9267,12 @@ var SubagentHandler = class {
|
|
|
9210
9267
|
}
|
|
9211
9268
|
// ───── Invoke ─────
|
|
9212
9269
|
async onInvoke(evt) {
|
|
9270
|
+
if (!this.config.autoAcceptInvokes) {
|
|
9271
|
+
return { error: { code: "provider_manual_mode", message: "invoke handling disabled" } };
|
|
9272
|
+
}
|
|
9273
|
+
if (this.config.capabilities && this.config.capabilities.length > 0 && !this.config.capabilities.includes(evt.capability)) {
|
|
9274
|
+
return { error: { code: "capability_not_supported", message: "capability not supported" } };
|
|
9275
|
+
}
|
|
9213
9276
|
const sessionKey = this.invokeKey(evt.invoke_id);
|
|
9214
9277
|
try {
|
|
9215
9278
|
const run = await this.api.runtime.subagent.run({
|
|
@@ -9218,7 +9281,7 @@ var SubagentHandler = class {
|
|
|
9218
9281
|
extraSystemPrompt: buildInvokePrompt(evt),
|
|
9219
9282
|
deliver: false
|
|
9220
9283
|
});
|
|
9221
|
-
const timeoutMs = (evt.timeout_seconds !== void 0 ? evt.timeout_seconds * 1e3 : this.config.invokeTimeoutMs) ??
|
|
9284
|
+
const timeoutMs = (evt.timeout_seconds !== void 0 ? evt.timeout_seconds * 1e3 : this.config.invokeTimeoutMs) ?? 6e4;
|
|
9222
9285
|
const waited = await this.api.runtime.subagent.waitForRun({ runId: run.runId, timeoutMs });
|
|
9223
9286
|
if (!isDone(waited.status)) {
|
|
9224
9287
|
return {
|
|
@@ -9486,6 +9549,7 @@ var SUPPORTED_CONFIG_FIELDS = /* @__PURE__ */ new Set([
|
|
|
9486
9549
|
"relayUrl",
|
|
9487
9550
|
"capabilities",
|
|
9488
9551
|
"autoStartProvider",
|
|
9552
|
+
"autoAcceptInvokes",
|
|
9489
9553
|
"autoAcceptSessions",
|
|
9490
9554
|
"autoAcceptGigTasks",
|
|
9491
9555
|
"invokeTimeoutMs",
|