@linkedclaw/openclaw-plugin 0.1.4 → 0.1.6
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 +10 -7
- package/dist/index.d.ts +2 -12
- package/dist/index.js +75 -47
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +4 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,8 @@ Requires Node.js 20+.
|
|
|
25
25
|
## Configuration
|
|
26
26
|
|
|
27
27
|
Config lives under `plugins.entries.linkedclaw.config` in your OpenClaw
|
|
28
|
-
gateway config. Minimum fields
|
|
28
|
+
gateway config. Minimum fields are `apiKey` and `agentId`; a typical provider
|
|
29
|
+
also keeps a local `capabilities` allow-list and explicit runtime limits:
|
|
29
30
|
|
|
30
31
|
```yaml
|
|
31
32
|
plugins:
|
|
@@ -34,9 +35,12 @@ plugins:
|
|
|
34
35
|
config:
|
|
35
36
|
apiKey: lc_xxxxxxxxxxxx
|
|
36
37
|
agentId: agt_xxxxxxxx # run `linkedclaw provider register` first
|
|
37
|
-
capabilities: [coding, review]
|
|
38
|
+
capabilities: [coding, review] # optional local allow-list
|
|
38
39
|
|
|
39
40
|
# Optional
|
|
41
|
+
cloudUrl: https://api.linkedclaw.com
|
|
42
|
+
serviceUrl: https://api.linkedclaw.com # services-host for gig-task accept/submit
|
|
43
|
+
relayUrl: wss://api.linkedclaw.com/ws
|
|
40
44
|
autoStartProvider: true # default true
|
|
41
45
|
autoAcceptSessions: true # default true
|
|
42
46
|
autoAcceptGigTasks: false # default false
|
|
@@ -45,13 +49,12 @@ plugins:
|
|
|
45
49
|
invokeTimeoutMs: 30000
|
|
46
50
|
sessionTurnTimeoutMs: 60000
|
|
47
51
|
gigTaskTimeoutMs: 300000
|
|
48
|
-
|
|
49
|
-
model: claude-opus-4-6
|
|
52
|
+
slaTier: standard
|
|
50
53
|
```
|
|
51
54
|
|
|
52
|
-
Listing metadata such as description and
|
|
53
|
-
listing registered through the `linkedclaw` CLI. The plugin config is
|
|
54
|
-
relay identity and local runtime behavior.
|
|
55
|
+
Listing metadata such as description and `capabilities_meta` lives in the
|
|
56
|
+
provider listing registered through the `linkedclaw` CLI. The plugin config is
|
|
57
|
+
only for relay identity and local runtime behavior.
|
|
55
58
|
|
|
56
59
|
## What it registers
|
|
57
60
|
|
package/dist/index.d.ts
CHANGED
|
@@ -117,34 +117,24 @@ interface PluginEntry {
|
|
|
117
117
|
register(api: OpenClawPluginApi): void | Promise<void>;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
interface CapabilityMetaEntry {
|
|
121
|
-
description: string;
|
|
122
|
-
has_side_effects?: boolean;
|
|
123
|
-
schema_url?: string;
|
|
124
|
-
schema_digest?: string;
|
|
125
|
-
}
|
|
126
120
|
interface ProviderConfig {
|
|
127
121
|
cloudUrl: string;
|
|
122
|
+
serviceUrl?: string;
|
|
128
123
|
relayUrl: string;
|
|
129
124
|
apiKey?: string;
|
|
130
125
|
agentId?: string;
|
|
131
|
-
agentName?: string;
|
|
132
126
|
capabilities: string[];
|
|
133
|
-
capabilitiesMeta?: Record<string, CapabilityMetaEntry>;
|
|
134
127
|
invokeTimeoutMs?: number;
|
|
135
128
|
sessionTurnTimeoutMs?: number;
|
|
136
129
|
gigTaskTimeoutMs?: number;
|
|
137
130
|
maxConcurrentRuns?: number;
|
|
138
131
|
perRequesterLimit?: number;
|
|
132
|
+
slaTier?: string;
|
|
139
133
|
}
|
|
140
134
|
interface PluginRuntimeConfig extends ProviderConfig {
|
|
141
135
|
autoStartProvider: boolean;
|
|
142
136
|
autoAcceptSessions: boolean;
|
|
143
137
|
autoAcceptGigTasks: boolean;
|
|
144
|
-
provider?: string;
|
|
145
|
-
model?: string;
|
|
146
|
-
agentDescription?: string;
|
|
147
|
-
slaTier?: string;
|
|
148
138
|
}
|
|
149
139
|
declare function parseConfig(raw: Record<string, unknown>): PluginRuntimeConfig;
|
|
150
140
|
|
package/dist/index.js
CHANGED
|
@@ -7896,6 +7896,20 @@ var GigTaskSchema = external_exports.object({
|
|
|
7896
7896
|
acceptance_criteria: external_exports.record(external_exports.unknown()).nullable().optional(),
|
|
7897
7897
|
expires_at: external_exports.string().nullable().optional()
|
|
7898
7898
|
}).passthrough();
|
|
7899
|
+
var GigTaskAvailableItemSchema = GigTaskSchema.extend({
|
|
7900
|
+
requester_reputation: external_exports.record(external_exports.unknown()).optional(),
|
|
7901
|
+
requester_slug: external_exports.string().nullable().optional(),
|
|
7902
|
+
is_locked: external_exports.boolean().optional(),
|
|
7903
|
+
lock_reason: external_exports.string().nullable().optional()
|
|
7904
|
+
}).passthrough();
|
|
7905
|
+
var GigTasksAvailableSchema = external_exports.object({
|
|
7906
|
+
viewer_tier: external_exports.object({
|
|
7907
|
+
name: external_exports.string().optional(),
|
|
7908
|
+
max_concurrent: external_exports.number().int().optional(),
|
|
7909
|
+
max_task_value: external_exports.number().int().nullable().optional()
|
|
7910
|
+
}).passthrough(),
|
|
7911
|
+
tasks: external_exports.array(GigTaskAvailableItemSchema)
|
|
7912
|
+
}).passthrough();
|
|
7899
7913
|
var GigTaskPolicySchema = external_exports.object({
|
|
7900
7914
|
max_credits_per_task: external_exports.number().int().optional(),
|
|
7901
7915
|
max_active_tasks: external_exports.number().int().optional()
|
|
@@ -8214,7 +8228,7 @@ var ProviderClient = class {
|
|
|
8214
8228
|
// ───────── Gig PA (provider) ─────────
|
|
8215
8229
|
/** @implements GET /api/v1/gig-tasks/available */
|
|
8216
8230
|
async listGigTasksAvailable(options) {
|
|
8217
|
-
return this.request(`/api/v1/gig-tasks/available${this.queryString({ capability: options?.capability })}`, { method: "GET" },
|
|
8231
|
+
return this.request(`/api/v1/gig-tasks/available${this.queryString({ capability: options?.capability })}`, { method: "GET" }, GigTasksAvailableSchema);
|
|
8218
8232
|
}
|
|
8219
8233
|
/** @implements GET /api/v1/gig-tasks/policy */
|
|
8220
8234
|
async getGigTaskPolicy() {
|
|
@@ -8388,7 +8402,7 @@ var MessageType = {
|
|
|
8388
8402
|
INVOKE_RESULT: "invoke_result"
|
|
8389
8403
|
};
|
|
8390
8404
|
function parseInbound(frame) {
|
|
8391
|
-
const type = frame
|
|
8405
|
+
const type = frame.type;
|
|
8392
8406
|
switch (type) {
|
|
8393
8407
|
case MessageType.SESSION_CREATE:
|
|
8394
8408
|
return {
|
|
@@ -8396,45 +8410,45 @@ function parseInbound(frame) {
|
|
|
8396
8410
|
session_id: str(frame, "session_id"),
|
|
8397
8411
|
requester_id: strOrEmpty(frame, "requester_id"),
|
|
8398
8412
|
capability: strOrEmpty(frame, "capability"),
|
|
8399
|
-
...frame
|
|
8413
|
+
...frame.scope !== void 0 ? { scope: frame.scope } : {}
|
|
8400
8414
|
};
|
|
8401
8415
|
case MessageType.SESSION_MESSAGE:
|
|
8402
8416
|
return {
|
|
8403
8417
|
type: "session.message",
|
|
8404
8418
|
session_id: str(frame, "session_id"),
|
|
8405
|
-
payload: frame
|
|
8406
|
-
...typeof frame
|
|
8407
|
-
...typeof frame
|
|
8419
|
+
payload: frame.payload,
|
|
8420
|
+
...typeof frame.seq === "number" ? { seq: frame.seq } : {},
|
|
8421
|
+
...typeof frame.sender === "string" ? { sender: frame.sender } : {}
|
|
8408
8422
|
};
|
|
8409
8423
|
case MessageType.SESSION_END:
|
|
8410
8424
|
return {
|
|
8411
8425
|
type: "session.end",
|
|
8412
8426
|
session_id: str(frame, "session_id"),
|
|
8413
|
-
...typeof frame
|
|
8427
|
+
...typeof frame.reason === "string" ? { reason: frame.reason } : {}
|
|
8414
8428
|
};
|
|
8415
8429
|
case MessageType.INVOKE:
|
|
8416
8430
|
return {
|
|
8417
8431
|
type: "invoke",
|
|
8418
8432
|
invoke_id: str(frame, "invoke_id"),
|
|
8419
8433
|
capability: strOrEmpty(frame, "capability"),
|
|
8420
|
-
input: frame
|
|
8421
|
-
...typeof frame
|
|
8422
|
-
...frame
|
|
8423
|
-
...typeof frame
|
|
8424
|
-
...typeof frame
|
|
8434
|
+
input: frame.input ?? {},
|
|
8435
|
+
...typeof frame.manifest_id === "string" ? { manifest_id: frame.manifest_id } : {},
|
|
8436
|
+
...frame.manifest !== void 0 && frame.manifest !== null ? { manifest: frame.manifest } : {},
|
|
8437
|
+
...typeof frame.requester_id === "string" ? { requester_id: frame.requester_id } : {},
|
|
8438
|
+
...typeof frame.timeout_seconds === "number" ? { timeout_seconds: frame.timeout_seconds } : {}
|
|
8425
8439
|
};
|
|
8426
8440
|
case MessageType.GIG_TASK: {
|
|
8427
8441
|
return {
|
|
8428
8442
|
type: "gig_task.offer",
|
|
8429
8443
|
task_id: str(frame, "task_id"),
|
|
8430
8444
|
capability: strOrEmpty(frame, "capability"),
|
|
8431
|
-
...typeof frame
|
|
8432
|
-
...typeof frame
|
|
8433
|
-
...typeof frame
|
|
8434
|
-
...typeof frame
|
|
8435
|
-
...typeof frame
|
|
8436
|
-
...frame
|
|
8437
|
-
...frame
|
|
8445
|
+
...typeof frame.instruction === "string" ? { instruction: frame.instruction } : {},
|
|
8446
|
+
...typeof frame.reward_credits === "number" ? { reward_credits: frame.reward_credits } : {},
|
|
8447
|
+
...typeof frame.response_sla_seconds === "number" ? { response_sla_seconds: frame.response_sla_seconds } : {},
|
|
8448
|
+
...typeof frame.slot_key === "string" ? { slot_key: frame.slot_key } : {},
|
|
8449
|
+
...typeof frame.partition_type === "string" ? { partition_type: frame.partition_type } : {},
|
|
8450
|
+
...frame.manifest !== void 0 && frame.manifest !== null ? { manifest: frame.manifest } : {},
|
|
8451
|
+
...frame.payload !== void 0 && frame.payload !== null ? { payload: frame.payload } : {}
|
|
8438
8452
|
};
|
|
8439
8453
|
}
|
|
8440
8454
|
default:
|
|
@@ -8702,10 +8716,11 @@ var DEFAULT_STRIP_PATTERNS = [
|
|
|
8702
8716
|
"system_prompt*"
|
|
8703
8717
|
];
|
|
8704
8718
|
function sanitizeText(text, patterns) {
|
|
8719
|
+
let result = text;
|
|
8705
8720
|
for (const pattern of patterns) {
|
|
8706
|
-
|
|
8721
|
+
result = result.replace(pattern, "");
|
|
8707
8722
|
}
|
|
8708
|
-
return
|
|
8723
|
+
return result;
|
|
8709
8724
|
}
|
|
8710
8725
|
function sanitizeOutput(payload, patterns = DEFAULT_OUTPUT_PATTERNS) {
|
|
8711
8726
|
if (typeof payload === "string") return sanitizeText(payload, patterns);
|
|
@@ -8868,7 +8883,7 @@ var ProviderRuntime = class {
|
|
|
8868
8883
|
return n;
|
|
8869
8884
|
}
|
|
8870
8885
|
async handleSessionCreate(evt) {
|
|
8871
|
-
const max = this.config.maxConcurrentRuns ??
|
|
8886
|
+
const max = this.config.maxConcurrentRuns ?? Number.POSITIVE_INFINITY;
|
|
8872
8887
|
if (this.totalInFlight() >= max) {
|
|
8873
8888
|
await this.send({
|
|
8874
8889
|
type: MessageType.SESSION_REJECT,
|
|
@@ -8954,7 +8969,7 @@ var ProviderRuntime = class {
|
|
|
8954
8969
|
}
|
|
8955
8970
|
}
|
|
8956
8971
|
async handleInvoke(evt) {
|
|
8957
|
-
const max = this.config.maxConcurrentRuns ??
|
|
8972
|
+
const max = this.config.maxConcurrentRuns ?? Number.POSITIVE_INFINITY;
|
|
8958
8973
|
if (this.totalInFlight() >= max) {
|
|
8959
8974
|
await this.send({
|
|
8960
8975
|
type: MessageType.INVOKE_RESULT,
|
|
@@ -8987,14 +9002,14 @@ var ProviderRuntime = class {
|
|
|
8987
9002
|
invoke_id: evt.invoke_id
|
|
8988
9003
|
};
|
|
8989
9004
|
if (result.error) {
|
|
8990
|
-
frame
|
|
9005
|
+
frame.error = result.error;
|
|
8991
9006
|
} else {
|
|
8992
|
-
frame
|
|
9007
|
+
frame.result = this.sanitizeOut(result.output ?? {});
|
|
8993
9008
|
}
|
|
8994
9009
|
await this.send(frame);
|
|
8995
9010
|
}
|
|
8996
9011
|
async handleGigTask(offer) {
|
|
8997
|
-
const max = this.config.maxConcurrentRuns ??
|
|
9012
|
+
const max = this.config.maxConcurrentRuns ?? Number.POSITIVE_INFINITY;
|
|
8998
9013
|
if (this.totalInFlight() >= max) return;
|
|
8999
9014
|
this.inFlightGigTasks.add(offer.task_id);
|
|
9000
9015
|
try {
|
|
@@ -9122,27 +9137,23 @@ function escapeRegex(s) {
|
|
|
9122
9137
|
function parseConfig(raw) {
|
|
9123
9138
|
const base = {
|
|
9124
9139
|
cloudUrl: typeof raw["cloudUrl"] === "string" ? raw["cloudUrl"] : process.env["LINKEDCLAW_CLOUD_URL"] ?? DEFAULT_CLOUD_URL,
|
|
9140
|
+
...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"] } : {},
|
|
9125
9141
|
relayUrl: typeof raw["relayUrl"] === "string" ? raw["relayUrl"] : process.env["LINKEDCLAW_RELAY_URL"] ?? DEFAULT_RELAY_URL,
|
|
9126
9142
|
capabilities: Array.isArray(raw["capabilities"]) ? raw["capabilities"] : [],
|
|
9127
|
-
...raw["capabilitiesMeta"] && typeof raw["capabilitiesMeta"] === "object" ? { capabilitiesMeta: raw["capabilitiesMeta"] } : {},
|
|
9128
9143
|
...typeof raw["apiKey"] === "string" ? { apiKey: raw["apiKey"] } : process.env["LINKEDCLAW_API_KEY"] !== void 0 ? { apiKey: process.env["LINKEDCLAW_API_KEY"] } : {},
|
|
9129
9144
|
...typeof raw["agentId"] === "string" ? { agentId: raw["agentId"] } : {},
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
...typeof raw["
|
|
9145
|
+
invokeTimeoutMs: typeof raw["invokeTimeoutMs"] === "number" ? raw["invokeTimeoutMs"] : 3e4,
|
|
9146
|
+
sessionTurnTimeoutMs: typeof raw["sessionTurnTimeoutMs"] === "number" ? raw["sessionTurnTimeoutMs"] : 6e4,
|
|
9147
|
+
gigTaskTimeoutMs: typeof raw["gigTaskTimeoutMs"] === "number" ? raw["gigTaskTimeoutMs"] : 3e5,
|
|
9148
|
+
maxConcurrentRuns: typeof raw["maxConcurrentRuns"] === "number" ? raw["maxConcurrentRuns"] : 4,
|
|
9149
|
+
perRequesterLimit: typeof raw["perRequesterLimit"] === "number" ? raw["perRequesterLimit"] : 2,
|
|
9150
|
+
...typeof raw["slaTier"] === "string" ? { slaTier: raw["slaTier"] } : {}
|
|
9136
9151
|
};
|
|
9137
9152
|
return {
|
|
9138
9153
|
...base,
|
|
9139
9154
|
autoStartProvider: raw["autoStartProvider"] !== false,
|
|
9140
9155
|
autoAcceptSessions: raw["autoAcceptSessions"] !== false,
|
|
9141
|
-
autoAcceptGigTasks: raw["autoAcceptGigTasks"] === true
|
|
9142
|
-
...typeof raw["provider"] === "string" ? { provider: raw["provider"] } : {},
|
|
9143
|
-
...typeof raw["model"] === "string" ? { model: raw["model"] } : {},
|
|
9144
|
-
...typeof raw["agentDescription"] === "string" ? { agentDescription: raw["agentDescription"] } : {},
|
|
9145
|
-
...typeof raw["slaTier"] === "string" ? { slaTier: raw["slaTier"] } : {}
|
|
9156
|
+
autoAcceptGigTasks: raw["autoAcceptGigTasks"] === true
|
|
9146
9157
|
};
|
|
9147
9158
|
}
|
|
9148
9159
|
|
|
@@ -9175,8 +9186,6 @@ var SubagentHandler = class {
|
|
|
9175
9186
|
sessionKey,
|
|
9176
9187
|
message,
|
|
9177
9188
|
extraSystemPrompt,
|
|
9178
|
-
...this.config.provider ? { provider: this.config.provider } : {},
|
|
9179
|
-
...this.config.model ? { model: this.config.model } : {},
|
|
9180
9189
|
deliver: false
|
|
9181
9190
|
});
|
|
9182
9191
|
const waited = await this.api.runtime.subagent.waitForRun({
|
|
@@ -9207,8 +9216,6 @@ var SubagentHandler = class {
|
|
|
9207
9216
|
sessionKey,
|
|
9208
9217
|
message: formatPayload(evt.input),
|
|
9209
9218
|
extraSystemPrompt: buildInvokePrompt(evt),
|
|
9210
|
-
...this.config.provider ? { provider: this.config.provider } : {},
|
|
9211
|
-
...this.config.model ? { model: this.config.model } : {},
|
|
9212
9219
|
deliver: false
|
|
9213
9220
|
});
|
|
9214
9221
|
const timeoutMs = (evt.timeout_seconds !== void 0 ? evt.timeout_seconds * 1e3 : this.config.invokeTimeoutMs) ?? 3e4;
|
|
@@ -9248,8 +9255,6 @@ var SubagentHandler = class {
|
|
|
9248
9255
|
sessionKey,
|
|
9249
9256
|
message: formatGigTask(evt),
|
|
9250
9257
|
extraSystemPrompt: buildGigTaskPrompt(evt),
|
|
9251
|
-
...this.config.provider ? { provider: this.config.provider } : {},
|
|
9252
|
-
...this.config.model ? { model: this.config.model } : {},
|
|
9253
9258
|
deliver: false
|
|
9254
9259
|
});
|
|
9255
9260
|
const timeoutMs = (evt.response_sla_seconds !== void 0 ? evt.response_sla_seconds * 1e3 : this.config.gigTaskTimeoutMs) ?? 3e5;
|
|
@@ -9431,7 +9436,7 @@ var ProviderHolder = class {
|
|
|
9431
9436
|
const agentId = cfg.agentId;
|
|
9432
9437
|
if (!apiKey) throw new Error("apiKey missing");
|
|
9433
9438
|
if (!agentId) throw new Error("agentId missing \u2014 register the provider first");
|
|
9434
|
-
const
|
|
9439
|
+
const gigTaskClient = new ProviderClient(cfg.serviceUrl ?? cfg.cloudUrl, apiKey);
|
|
9435
9440
|
const relay = new RelayClient({
|
|
9436
9441
|
url: cfg.relayUrl,
|
|
9437
9442
|
apiKey,
|
|
@@ -9442,8 +9447,8 @@ var ProviderHolder = class {
|
|
|
9442
9447
|
return new ProviderRuntime({
|
|
9443
9448
|
cloud: {
|
|
9444
9449
|
gigTasks: {
|
|
9445
|
-
accept: (taskId, body, idempotencyKey) =>
|
|
9446
|
-
submit: (taskId, body) =>
|
|
9450
|
+
accept: (taskId, body, idempotencyKey) => gigTaskClient.acceptGigTask(taskId, body, idempotencyKey),
|
|
9451
|
+
submit: (taskId, body) => gigTaskClient.submitGigTask(taskId, body)
|
|
9447
9452
|
}
|
|
9448
9453
|
},
|
|
9449
9454
|
relay,
|
|
@@ -9473,6 +9478,23 @@ var USAGE = [
|
|
|
9473
9478
|
"`/linkedclaw restart` afterwards to make them take effect."
|
|
9474
9479
|
].join("\n");
|
|
9475
9480
|
var REDACTED_FIELDS = /* @__PURE__ */ new Set(["apiKey"]);
|
|
9481
|
+
var SUPPORTED_CONFIG_FIELDS = /* @__PURE__ */ new Set([
|
|
9482
|
+
"apiKey",
|
|
9483
|
+
"agentId",
|
|
9484
|
+
"cloudUrl",
|
|
9485
|
+
"serviceUrl",
|
|
9486
|
+
"relayUrl",
|
|
9487
|
+
"capabilities",
|
|
9488
|
+
"autoStartProvider",
|
|
9489
|
+
"autoAcceptSessions",
|
|
9490
|
+
"autoAcceptGigTasks",
|
|
9491
|
+
"invokeTimeoutMs",
|
|
9492
|
+
"sessionTurnTimeoutMs",
|
|
9493
|
+
"gigTaskTimeoutMs",
|
|
9494
|
+
"maxConcurrentRuns",
|
|
9495
|
+
"perRequesterLimit",
|
|
9496
|
+
"slaTier"
|
|
9497
|
+
]);
|
|
9476
9498
|
function buildLinkedClawCommand(holder) {
|
|
9477
9499
|
return {
|
|
9478
9500
|
name: "linkedclaw",
|
|
@@ -9544,6 +9566,12 @@ async function handleConfig(holder, args) {
|
|
|
9544
9566
|
if (!key || valueParts.length === 0) {
|
|
9545
9567
|
return fail("usage: /linkedclaw config set <key> <value>");
|
|
9546
9568
|
}
|
|
9569
|
+
if (!SUPPORTED_CONFIG_FIELDS.has(key)) {
|
|
9570
|
+
return fail(
|
|
9571
|
+
`unsupported config field: ${key}
|
|
9572
|
+
supported fields: ${Array.from(SUPPORTED_CONFIG_FIELDS).sort().join(", ")}`
|
|
9573
|
+
);
|
|
9574
|
+
}
|
|
9547
9575
|
const parsed = parseConfigValue(valueParts.join(" "));
|
|
9548
9576
|
updateLinkedClawPluginConfig((cfg) => {
|
|
9549
9577
|
cfg[key] = parsed;
|