@agentvault/agentvault 0.15.3 → 0.17.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/channel.d.ts +10 -1
- package/dist/channel.d.ts.map +1 -1
- package/dist/cli.js +423 -89
- package/dist/cli.js.map +4 -4
- package/dist/gateway-send.d.ts +34 -0
- package/dist/gateway-send.d.ts.map +1 -1
- package/dist/http-handlers.d.ts +10 -0
- package/dist/http-handlers.d.ts.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +623 -89
- package/dist/index.js.map +4 -4
- package/dist/mcp-server.d.ts +18 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/openclaw-entry.d.ts.map +1 -1
- package/dist/openclaw-entry.js +132 -77
- package/dist/openclaw-entry.js.map +4 -4
- package/dist/policy-enforcer.d.ts +78 -0
- package/dist/policy-enforcer.d.ts.map +1 -0
- package/dist/skill-manifest.d.ts.map +1 -1
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -45996,6 +45996,37 @@ function buildEvalSpan(opts) {
|
|
|
45996
45996
|
status: { code: 0 }
|
|
45997
45997
|
};
|
|
45998
45998
|
}
|
|
45999
|
+
function buildPolicyViolationSpan(opts) {
|
|
46000
|
+
const now = Date.now();
|
|
46001
|
+
const attributes = {
|
|
46002
|
+
"av.policy.rule_id": opts.ruleId,
|
|
46003
|
+
"av.policy.scope": opts.policyScope,
|
|
46004
|
+
"av.policy.action_taken": opts.actionTaken,
|
|
46005
|
+
"av.policy.violation_type": opts.violationType
|
|
46006
|
+
};
|
|
46007
|
+
if (opts.targetTool)
|
|
46008
|
+
attributes["av.policy.target_tool"] = opts.targetTool;
|
|
46009
|
+
if (opts.targetModel)
|
|
46010
|
+
attributes["av.policy.target_model"] = opts.targetModel;
|
|
46011
|
+
if (opts.messageType)
|
|
46012
|
+
attributes["av.policy.message_type"] = opts.messageType;
|
|
46013
|
+
applySkillName(attributes, opts.skillName);
|
|
46014
|
+
const isBlock = opts.actionTaken === "block";
|
|
46015
|
+
return {
|
|
46016
|
+
traceId: opts.traceId ?? generateTraceId(),
|
|
46017
|
+
spanId: opts.spanId ?? generateSpanId(),
|
|
46018
|
+
parentSpanId: opts.parentSpanId,
|
|
46019
|
+
name: "av.policy.evaluate",
|
|
46020
|
+
kind: "internal",
|
|
46021
|
+
startTime: now,
|
|
46022
|
+
endTime: now,
|
|
46023
|
+
attributes,
|
|
46024
|
+
status: isBlock ? { code: 2, message: `Policy violation: ${opts.violationType}` } : { code: 0 }
|
|
46025
|
+
};
|
|
46026
|
+
}
|
|
46027
|
+
function buildTraceparent(span) {
|
|
46028
|
+
return `00-${span.traceId}-${span.spanId}-01`;
|
|
46029
|
+
}
|
|
45999
46030
|
var init_telemetry = __esm({
|
|
46000
46031
|
"../crypto/dist/telemetry.js"() {
|
|
46001
46032
|
"use strict";
|
|
@@ -46018,6 +46049,9 @@ function toOtlpAttributes(attrs) {
|
|
|
46018
46049
|
});
|
|
46019
46050
|
}
|
|
46020
46051
|
function spanToOtlp(span) {
|
|
46052
|
+
const enrichedAttrs = { ...span.attributes };
|
|
46053
|
+
enrichedAttrs["w3c.traceparent"] = buildTraceparent(span);
|
|
46054
|
+
enrichedAttrs["w3c.tracestate"] = `av=s:${span.spanId}`;
|
|
46021
46055
|
const otlp = {
|
|
46022
46056
|
traceId: span.traceId,
|
|
46023
46057
|
spanId: span.spanId,
|
|
@@ -46025,7 +46059,7 @@ function spanToOtlp(span) {
|
|
|
46025
46059
|
kind: span.kind,
|
|
46026
46060
|
startTimeUnixNano: String(span.startTime * 1e6),
|
|
46027
46061
|
endTimeUnixNano: String(span.endTime * 1e6),
|
|
46028
|
-
attributes: toOtlpAttributes(
|
|
46062
|
+
attributes: toOtlpAttributes(enrichedAttrs)
|
|
46029
46063
|
};
|
|
46030
46064
|
if (span.parentSpanId !== void 0) {
|
|
46031
46065
|
otlp.parentSpanId = span.parentSpanId;
|
|
@@ -46202,6 +46236,14 @@ var init_backup = __esm({
|
|
|
46202
46236
|
}
|
|
46203
46237
|
});
|
|
46204
46238
|
|
|
46239
|
+
// ../crypto/dist/approval.js
|
|
46240
|
+
var init_approval = __esm({
|
|
46241
|
+
async "../crypto/dist/approval.js"() {
|
|
46242
|
+
"use strict";
|
|
46243
|
+
await init_did();
|
|
46244
|
+
}
|
|
46245
|
+
});
|
|
46246
|
+
|
|
46205
46247
|
// ../crypto/dist/index.js
|
|
46206
46248
|
var init_dist = __esm({
|
|
46207
46249
|
async "../crypto/dist/index.js"() {
|
|
@@ -46219,6 +46261,7 @@ var init_dist = __esm({
|
|
|
46219
46261
|
init_telemetry();
|
|
46220
46262
|
init_telemetry_reporter();
|
|
46221
46263
|
await init_backup();
|
|
46264
|
+
await init_approval();
|
|
46222
46265
|
}
|
|
46223
46266
|
});
|
|
46224
46267
|
|
|
@@ -46496,7 +46539,8 @@ __export(http_handlers_exports, {
|
|
|
46496
46539
|
handleActionRequest: () => handleActionRequest,
|
|
46497
46540
|
handleDecisionRequest: () => handleDecisionRequest,
|
|
46498
46541
|
handleSendRequest: () => handleSendRequest,
|
|
46499
|
-
handleStatusRequest: () => handleStatusRequest
|
|
46542
|
+
handleStatusRequest: () => handleStatusRequest,
|
|
46543
|
+
handleTargetsRequest: () => handleTargetsRequest
|
|
46500
46544
|
});
|
|
46501
46545
|
async function handleSendRequest(parsed, channel) {
|
|
46502
46546
|
const text = parsed.text;
|
|
@@ -46504,32 +46548,55 @@ async function handleSendRequest(parsed, channel) {
|
|
|
46504
46548
|
return { status: 400, body: { ok: false, error: "Missing 'text' field" } };
|
|
46505
46549
|
}
|
|
46506
46550
|
try {
|
|
46551
|
+
let target;
|
|
46507
46552
|
let a2aTarget = parsed.hub_address ?? parsed.a2a_address ?? parsed.a2aAddress;
|
|
46508
46553
|
if (!a2aTarget && parsed.channel_id && typeof parsed.channel_id === "string") {
|
|
46509
46554
|
const hubAddr = channel.resolveA2AChannelHub(parsed.channel_id);
|
|
46510
46555
|
if (hubAddr) a2aTarget = hubAddr;
|
|
46511
46556
|
}
|
|
46512
|
-
const roomId = (typeof parsed.room_id === "string" ? parsed.room_id : void 0) ?? channel.lastInboundRoomId;
|
|
46513
46557
|
if (a2aTarget && typeof a2aTarget === "string") {
|
|
46514
|
-
|
|
46515
|
-
} else if (
|
|
46516
|
-
|
|
46517
|
-
|
|
46518
|
-
|
|
46519
|
-
metadata: parsed.metadata
|
|
46520
|
-
});
|
|
46558
|
+
target = { kind: "a2a", hubAddress: a2aTarget };
|
|
46559
|
+
} else if (typeof parsed.room_id === "string") {
|
|
46560
|
+
target = { kind: "room", roomId: parsed.room_id };
|
|
46561
|
+
} else if (parsed.target === "context") {
|
|
46562
|
+
target = { kind: "context" };
|
|
46521
46563
|
} else if (parsed.file_path && typeof parsed.file_path === "string") {
|
|
46522
|
-
await channel.
|
|
46523
|
-
|
|
46524
|
-
|
|
46564
|
+
const receipt2 = await channel.deliver(
|
|
46565
|
+
{ kind: "owner" },
|
|
46566
|
+
{ type: "attachment", text, filePath: parsed.file_path },
|
|
46567
|
+
{ topicId: parsed.topicId }
|
|
46568
|
+
);
|
|
46569
|
+
return {
|
|
46570
|
+
status: receipt2.ok ? 200 : 500,
|
|
46571
|
+
body: {
|
|
46572
|
+
ok: receipt2.ok,
|
|
46573
|
+
destination: receipt2.destination,
|
|
46574
|
+
...receipt2.error ? { error: receipt2.error } : {}
|
|
46575
|
+
}
|
|
46576
|
+
};
|
|
46525
46577
|
} else {
|
|
46526
|
-
|
|
46527
|
-
topicId: parsed.topicId,
|
|
46528
|
-
messageType: parsed.message_type,
|
|
46529
|
-
metadata: parsed.metadata
|
|
46530
|
-
});
|
|
46578
|
+
target = { kind: "owner" };
|
|
46531
46579
|
}
|
|
46532
|
-
|
|
46580
|
+
const receipt = await channel.deliver(
|
|
46581
|
+
target,
|
|
46582
|
+
{ type: "text", text },
|
|
46583
|
+
{
|
|
46584
|
+
topicId: parsed.topicId,
|
|
46585
|
+
priority: parsed.priority,
|
|
46586
|
+
metadata: {
|
|
46587
|
+
...parsed.metadata,
|
|
46588
|
+
...parsed.message_type ? { message_type: parsed.message_type } : {}
|
|
46589
|
+
}
|
|
46590
|
+
}
|
|
46591
|
+
);
|
|
46592
|
+
return {
|
|
46593
|
+
status: receipt.ok ? 200 : 500,
|
|
46594
|
+
body: {
|
|
46595
|
+
ok: receipt.ok,
|
|
46596
|
+
destination: receipt.destination,
|
|
46597
|
+
...receipt.error ? { error: receipt.error } : {}
|
|
46598
|
+
}
|
|
46599
|
+
};
|
|
46533
46600
|
} catch (err) {
|
|
46534
46601
|
return { status: 500, body: { ok: false, error: String(err) } };
|
|
46535
46602
|
}
|
|
@@ -46546,12 +46613,19 @@ async function handleActionRequest(parsed, channel) {
|
|
|
46546
46613
|
detail: parsed.detail,
|
|
46547
46614
|
estimated_cost: parsed.estimated_cost
|
|
46548
46615
|
};
|
|
46549
|
-
|
|
46550
|
-
|
|
46551
|
-
|
|
46552
|
-
|
|
46553
|
-
|
|
46554
|
-
return {
|
|
46616
|
+
const target = parsed.room_id && typeof parsed.room_id === "string" ? { kind: "room", roomId: parsed.room_id } : { kind: "owner" };
|
|
46617
|
+
const receipt = await channel.deliver(
|
|
46618
|
+
target,
|
|
46619
|
+
{ type: "action_confirmation", confirmation }
|
|
46620
|
+
);
|
|
46621
|
+
return {
|
|
46622
|
+
status: receipt.ok ? 200 : 500,
|
|
46623
|
+
body: {
|
|
46624
|
+
ok: receipt.ok,
|
|
46625
|
+
destination: receipt.destination,
|
|
46626
|
+
...receipt.error ? { error: receipt.error } : {}
|
|
46627
|
+
}
|
|
46628
|
+
};
|
|
46555
46629
|
} catch (err) {
|
|
46556
46630
|
return { status: 500, body: { ok: false, error: String(err) } };
|
|
46557
46631
|
}
|
|
@@ -46595,6 +46669,16 @@ function handleStatusRequest(channel) {
|
|
|
46595
46669
|
}
|
|
46596
46670
|
};
|
|
46597
46671
|
}
|
|
46672
|
+
function handleTargetsRequest(channel) {
|
|
46673
|
+
return {
|
|
46674
|
+
status: 200,
|
|
46675
|
+
body: {
|
|
46676
|
+
ok: true,
|
|
46677
|
+
targets: channel.listTargets(),
|
|
46678
|
+
context: channel.lastInboundRoomId ? { kind: "room", roomId: channel.lastInboundRoomId } : { kind: "owner" }
|
|
46679
|
+
}
|
|
46680
|
+
};
|
|
46681
|
+
}
|
|
46598
46682
|
var init_http_handlers = __esm({
|
|
46599
46683
|
"src/http-handlers.ts"() {
|
|
46600
46684
|
"use strict";
|
|
@@ -47574,6 +47658,171 @@ var init_channel = __esm({
|
|
|
47574
47658
|
metadata
|
|
47575
47659
|
});
|
|
47576
47660
|
}
|
|
47661
|
+
// --- Unified Delivery Protocol ---
|
|
47662
|
+
/**
|
|
47663
|
+
* Canonical message dispatcher. ALL outbound messages should flow through this method.
|
|
47664
|
+
* Routes based on explicit target — never silently falls back to a room.
|
|
47665
|
+
*/
|
|
47666
|
+
async deliver(target, content, options) {
|
|
47667
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
47668
|
+
if (this._state === "idle" || this._state === "error") {
|
|
47669
|
+
return {
|
|
47670
|
+
ok: false,
|
|
47671
|
+
destination: { kind: "owner" },
|
|
47672
|
+
error: `Channel is in ${this._state} state`,
|
|
47673
|
+
timestamp: ts
|
|
47674
|
+
};
|
|
47675
|
+
}
|
|
47676
|
+
let resolved;
|
|
47677
|
+
if (target.kind === "context") {
|
|
47678
|
+
if (this._lastInboundRoomId) {
|
|
47679
|
+
resolved = { kind: "room", id: this._lastInboundRoomId };
|
|
47680
|
+
console.log(`[deliver] target=context\u2192room:${this._lastInboundRoomId.slice(0, 8)}...`);
|
|
47681
|
+
} else {
|
|
47682
|
+
resolved = { kind: "owner" };
|
|
47683
|
+
console.log(`[deliver] target=context\u2192owner`);
|
|
47684
|
+
}
|
|
47685
|
+
} else if (target.kind === "owner") {
|
|
47686
|
+
resolved = { kind: "owner" };
|
|
47687
|
+
} else if (target.kind === "room") {
|
|
47688
|
+
if (!this._persisted?.rooms?.[target.roomId]) {
|
|
47689
|
+
const err = `Room ${target.roomId} not found`;
|
|
47690
|
+
console.log(`[deliver] target=room:${target.roomId.slice(0, 8)}... content=${content.type} result=FAIL: ${err}`);
|
|
47691
|
+
return { ok: false, destination: { kind: "room", id: target.roomId }, error: err, timestamp: ts };
|
|
47692
|
+
}
|
|
47693
|
+
resolved = { kind: "room", id: target.roomId };
|
|
47694
|
+
} else if (target.kind === "a2a") {
|
|
47695
|
+
const channelEntry = this._persisted?.a2aChannels ? Object.values(this._persisted.a2aChannels).find((ch) => ch.hubAddress === target.hubAddress) : void 0;
|
|
47696
|
+
if (!channelEntry) {
|
|
47697
|
+
const err = `No A2A channel found for hub address: ${target.hubAddress}`;
|
|
47698
|
+
console.log(`[deliver] target=a2a:${target.hubAddress} content=${content.type} result=FAIL: ${err}`);
|
|
47699
|
+
return { ok: false, destination: { kind: "a2a", id: target.hubAddress }, error: err, timestamp: ts };
|
|
47700
|
+
}
|
|
47701
|
+
resolved = { kind: "a2a", id: target.hubAddress };
|
|
47702
|
+
} else {
|
|
47703
|
+
return { ok: false, destination: { kind: "owner" }, error: "Unknown target kind", timestamp: ts };
|
|
47704
|
+
}
|
|
47705
|
+
try {
|
|
47706
|
+
let decisionId;
|
|
47707
|
+
if (content.type === "text") {
|
|
47708
|
+
if (resolved.kind === "room") {
|
|
47709
|
+
await this.sendToRoom(resolved.id, content.text, {
|
|
47710
|
+
messageType: options?.metadata?.message_type,
|
|
47711
|
+
priority: options?.priority,
|
|
47712
|
+
metadata: options?.metadata
|
|
47713
|
+
});
|
|
47714
|
+
} else if (resolved.kind === "a2a") {
|
|
47715
|
+
await this.sendToAgent(resolved.id, content.text, {
|
|
47716
|
+
parentSpanId: options?.parentSpanId
|
|
47717
|
+
});
|
|
47718
|
+
} else {
|
|
47719
|
+
await this.send(content.text, {
|
|
47720
|
+
conversationId: options?.conversationId,
|
|
47721
|
+
topicId: options?.topicId,
|
|
47722
|
+
messageType: options?.metadata?.message_type,
|
|
47723
|
+
priority: options?.priority,
|
|
47724
|
+
metadata: options?.metadata
|
|
47725
|
+
});
|
|
47726
|
+
}
|
|
47727
|
+
} else if (content.type === "decision_request") {
|
|
47728
|
+
if (resolved.kind !== "owner") {
|
|
47729
|
+
const err = "Decision requests can only be sent to owner";
|
|
47730
|
+
console.log(`[deliver] target=${resolved.kind}:${resolved.id} content=decision_request result=FAIL: ${err}`);
|
|
47731
|
+
return { ok: false, destination: resolved, error: err, timestamp: ts };
|
|
47732
|
+
}
|
|
47733
|
+
decisionId = await this.sendDecisionRequest(content.request);
|
|
47734
|
+
} else if (content.type === "status_alert") {
|
|
47735
|
+
if (resolved.kind === "room") {
|
|
47736
|
+
const envelope = {
|
|
47737
|
+
title: content.alert.title,
|
|
47738
|
+
message: content.alert.message,
|
|
47739
|
+
severity: content.alert.severity,
|
|
47740
|
+
timestamp: ts
|
|
47741
|
+
};
|
|
47742
|
+
if (content.alert.detail !== void 0) envelope.detail = content.alert.detail;
|
|
47743
|
+
if (content.alert.detailFormat !== void 0) envelope.detail_format = content.alert.detailFormat;
|
|
47744
|
+
if (content.alert.category !== void 0) envelope.category = content.alert.category;
|
|
47745
|
+
await this.sendToRoom(resolved.id, JSON.stringify(envelope), {
|
|
47746
|
+
messageType: "status_alert",
|
|
47747
|
+
priority: content.alert.severity === "error" || content.alert.severity === "critical" ? "high" : "normal",
|
|
47748
|
+
metadata: { severity: content.alert.severity }
|
|
47749
|
+
});
|
|
47750
|
+
} else if (resolved.kind === "owner") {
|
|
47751
|
+
await this.sendStatusAlert(content.alert);
|
|
47752
|
+
} else {
|
|
47753
|
+
return { ok: false, destination: resolved, error: "Status alerts cannot be sent to A2A targets", timestamp: ts };
|
|
47754
|
+
}
|
|
47755
|
+
} else if (content.type === "action_confirmation") {
|
|
47756
|
+
if (resolved.kind === "room") {
|
|
47757
|
+
await this.sendActionConfirmationToRoom(resolved.id, content.confirmation);
|
|
47758
|
+
} else if (resolved.kind === "owner") {
|
|
47759
|
+
await this.sendActionConfirmation(content.confirmation);
|
|
47760
|
+
} else {
|
|
47761
|
+
return { ok: false, destination: resolved, error: "Action confirmations cannot be sent to A2A targets", timestamp: ts };
|
|
47762
|
+
}
|
|
47763
|
+
} else if (content.type === "artifact") {
|
|
47764
|
+
if (resolved.kind !== "owner") {
|
|
47765
|
+
return { ok: false, destination: resolved, error: "Artifacts can only be sent to owner", timestamp: ts };
|
|
47766
|
+
}
|
|
47767
|
+
await this.sendArtifact(content.artifact);
|
|
47768
|
+
} else if (content.type === "attachment") {
|
|
47769
|
+
if (resolved.kind !== "owner") {
|
|
47770
|
+
return { ok: false, destination: resolved, error: "Attachments can only be sent to owner", timestamp: ts };
|
|
47771
|
+
}
|
|
47772
|
+
await this.sendWithAttachment(content.text, content.filePath, {
|
|
47773
|
+
topicId: options?.topicId
|
|
47774
|
+
});
|
|
47775
|
+
}
|
|
47776
|
+
const targetLabel = resolved.kind === "owner" ? "owner" : `${resolved.kind}:${resolved.id?.slice(0, 8)}...`;
|
|
47777
|
+
console.log(`[deliver] target=${targetLabel} content=${content.type} result=ok`);
|
|
47778
|
+
return {
|
|
47779
|
+
ok: true,
|
|
47780
|
+
destination: resolved,
|
|
47781
|
+
queued: this._state !== "ready",
|
|
47782
|
+
decisionId,
|
|
47783
|
+
timestamp: ts
|
|
47784
|
+
};
|
|
47785
|
+
} catch (err) {
|
|
47786
|
+
const targetLabel = resolved.kind === "owner" ? "owner" : `${resolved.kind}:${resolved.id?.slice(0, 8)}...`;
|
|
47787
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
47788
|
+
console.log(`[deliver] target=${targetLabel} content=${content.type} result=FAIL: ${errMsg}`);
|
|
47789
|
+
return { ok: false, destination: resolved, error: errMsg, timestamp: ts };
|
|
47790
|
+
}
|
|
47791
|
+
}
|
|
47792
|
+
/**
|
|
47793
|
+
* Returns all available delivery destinations with availability status.
|
|
47794
|
+
*/
|
|
47795
|
+
listTargets() {
|
|
47796
|
+
const targets = [
|
|
47797
|
+
{
|
|
47798
|
+
kind: "owner",
|
|
47799
|
+
id: "owner",
|
|
47800
|
+
label: "Owner (direct)",
|
|
47801
|
+
available: this._state === "ready" && this._sessions.size > 0
|
|
47802
|
+
}
|
|
47803
|
+
];
|
|
47804
|
+
if (this._persisted?.rooms) {
|
|
47805
|
+
for (const room of Object.values(this._persisted.rooms)) {
|
|
47806
|
+
targets.push({
|
|
47807
|
+
kind: "room",
|
|
47808
|
+
id: room.roomId,
|
|
47809
|
+
label: room.name || `Room ${room.roomId.slice(0, 8)}`,
|
|
47810
|
+
available: this._state === "ready" && room.conversationIds.length > 0
|
|
47811
|
+
});
|
|
47812
|
+
}
|
|
47813
|
+
}
|
|
47814
|
+
if (this._persisted?.a2aChannels) {
|
|
47815
|
+
for (const ch of Object.values(this._persisted.a2aChannels)) {
|
|
47816
|
+
targets.push({
|
|
47817
|
+
kind: "a2a",
|
|
47818
|
+
id: ch.hubAddress,
|
|
47819
|
+
label: `A2A: ${ch.hubAddress}`,
|
|
47820
|
+
available: this._state === "ready" && !!ch.session?.ratchetState
|
|
47821
|
+
});
|
|
47822
|
+
}
|
|
47823
|
+
}
|
|
47824
|
+
return targets;
|
|
47825
|
+
}
|
|
47577
47826
|
_sendHeartbeat() {
|
|
47578
47827
|
if (this._state !== "ready" || !this._heartbeatCallback) return;
|
|
47579
47828
|
const status = this._heartbeatCallback();
|
|
@@ -47692,9 +47941,13 @@ var init_channel = __esm({
|
|
|
47692
47941
|
const result = handlers.handleStatusRequest(this);
|
|
47693
47942
|
res.writeHead(result.status, { "Content-Type": "application/json" });
|
|
47694
47943
|
res.end(JSON.stringify(result.body));
|
|
47944
|
+
} else if (req.method === "GET" && req.url === "/targets") {
|
|
47945
|
+
const result = handlers.handleTargetsRequest(this);
|
|
47946
|
+
res.writeHead(result.status, { "Content-Type": "application/json" });
|
|
47947
|
+
res.end(JSON.stringify(result.body));
|
|
47695
47948
|
} else {
|
|
47696
47949
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
47697
|
-
res.end(JSON.stringify({ ok: false, error: "Not found. Use POST /send, POST /decision, POST /action, or GET /
|
|
47950
|
+
res.end(JSON.stringify({ ok: false, error: "Not found. Use POST /send, POST /decision, POST /action, GET /status, or GET /targets" }));
|
|
47698
47951
|
}
|
|
47699
47952
|
});
|
|
47700
47953
|
this._httpServer.listen(port, "127.0.0.1", () => {
|
|
@@ -48303,10 +48556,11 @@ var init_channel = __esm({
|
|
|
48303
48556
|
}
|
|
48304
48557
|
if (data.event === "hub_identity_sync") {
|
|
48305
48558
|
if (this._persisted && data.data?.hub_id) {
|
|
48306
|
-
const changed = this._persisted.hubId !== data.data.hub_id;
|
|
48559
|
+
const changed = this._persisted.hubId !== data.data.hub_id || this._persisted.agentRole !== (data.data.agent_role ?? "peer");
|
|
48307
48560
|
this._persisted.hubAddress = data.data.hub_address;
|
|
48308
48561
|
this._persisted.hubId = data.data.hub_id;
|
|
48309
48562
|
this._persisted.agentHubId = data.data.hub_id;
|
|
48563
|
+
this._persisted.agentRole = data.data.agent_role ?? "peer";
|
|
48310
48564
|
if (changed) this._persistState();
|
|
48311
48565
|
if (!this._telemetryReporter && this._persisted.deviceJwt && this._persisted.hubId) {
|
|
48312
48566
|
this._telemetryReporter = new TelemetryReporter({
|
|
@@ -48328,6 +48582,14 @@ var init_channel = __esm({
|
|
|
48328
48582
|
}
|
|
48329
48583
|
this.emit("hub_identity_assigned", data.data);
|
|
48330
48584
|
}
|
|
48585
|
+
if (data.event === "hub_identity_role_changed") {
|
|
48586
|
+
if (this._persisted && data.data?.agent_role) {
|
|
48587
|
+
this._persisted.agentRole = data.data.agent_role;
|
|
48588
|
+
this._persistState();
|
|
48589
|
+
console.log(`[SecureChannel] Agent role changed to: ${data.data.agent_role}`);
|
|
48590
|
+
}
|
|
48591
|
+
this.emit("hub_identity_role_changed", data.data);
|
|
48592
|
+
}
|
|
48331
48593
|
if (data.event === "hub_identity_removed") {
|
|
48332
48594
|
if (this._persisted) {
|
|
48333
48595
|
delete this._persisted.hubAddress;
|
|
@@ -48994,6 +49256,9 @@ ${messageText}`;
|
|
|
48994
49256
|
_resolveWorkspaceDir() {
|
|
48995
49257
|
const homedir = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
|
|
48996
49258
|
const agentName = this.config.agentName;
|
|
49259
|
+
if (this._persisted?.agentRole === "lead") {
|
|
49260
|
+
return join3(homedir, ".openclaw", "workspace");
|
|
49261
|
+
}
|
|
48997
49262
|
try {
|
|
48998
49263
|
const configPath = join3(homedir, ".openclaw", "openclaw.json");
|
|
48999
49264
|
const raw = __require("node:fs").readFileSync(configPath, "utf-8");
|
|
@@ -50015,6 +50280,39 @@ ${messageText}`;
|
|
|
50015
50280
|
}
|
|
50016
50281
|
});
|
|
50017
50282
|
|
|
50283
|
+
// src/types.ts
|
|
50284
|
+
function parseTarget(raw) {
|
|
50285
|
+
let target = raw;
|
|
50286
|
+
if (target.startsWith("agentvault:")) {
|
|
50287
|
+
target = target.slice("agentvault:".length);
|
|
50288
|
+
}
|
|
50289
|
+
if (target.startsWith("agent:")) {
|
|
50290
|
+
target = "a2a:" + target.slice("agent:".length);
|
|
50291
|
+
}
|
|
50292
|
+
if (target === "owner" || target === "default") {
|
|
50293
|
+
return { kind: "owner" };
|
|
50294
|
+
}
|
|
50295
|
+
if (target === "context") {
|
|
50296
|
+
return { kind: "context" };
|
|
50297
|
+
}
|
|
50298
|
+
if (target.startsWith("room:")) {
|
|
50299
|
+
const roomId = target.slice("room:".length);
|
|
50300
|
+
if (!roomId) throw new Error(`Invalid room target: "${raw}" \u2014 missing room ID`);
|
|
50301
|
+
return { kind: "room", roomId };
|
|
50302
|
+
}
|
|
50303
|
+
if (target.startsWith("a2a:")) {
|
|
50304
|
+
const hubAddress = target.slice("a2a:".length);
|
|
50305
|
+
if (!hubAddress) throw new Error(`Invalid A2A target: "${raw}" \u2014 missing hub address`);
|
|
50306
|
+
return { kind: "a2a", hubAddress };
|
|
50307
|
+
}
|
|
50308
|
+
throw new Error(`Unrecognized delivery target: "${raw}". Use "owner", "room:<id>", "a2a:<addr>", or "context".`);
|
|
50309
|
+
}
|
|
50310
|
+
var init_types = __esm({
|
|
50311
|
+
"src/types.ts"() {
|
|
50312
|
+
"use strict";
|
|
50313
|
+
}
|
|
50314
|
+
});
|
|
50315
|
+
|
|
50018
50316
|
// src/account-config.ts
|
|
50019
50317
|
function listAccountIds(cfg) {
|
|
50020
50318
|
const av = cfg?.channels?.agentvault;
|
|
@@ -50408,6 +50706,88 @@ async function sendDecisionToOwner(request, options) {
|
|
|
50408
50706
|
return { ok: false, error: friendlyError(err) };
|
|
50409
50707
|
}
|
|
50410
50708
|
}
|
|
50709
|
+
async function sendToRoom(roomId, text, options) {
|
|
50710
|
+
if (typeof text !== "string" || text.trim().length === 0) {
|
|
50711
|
+
return { ok: false, error: "Message text must be a non-empty string" };
|
|
50712
|
+
}
|
|
50713
|
+
if (!roomId) {
|
|
50714
|
+
return { ok: false, error: "Room ID is required" };
|
|
50715
|
+
}
|
|
50716
|
+
requestHeartbeatNow({ reason: "proactive-room-send" }).catch(() => {
|
|
50717
|
+
});
|
|
50718
|
+
try {
|
|
50719
|
+
const base = resolveBaseUrl(options);
|
|
50720
|
+
const sendPath = process.env.OPENCLAW_GATEWAY_URL ? "/agentvault/send" : "/send";
|
|
50721
|
+
const res = await fetch(`${base}${sendPath}`, {
|
|
50722
|
+
method: "POST",
|
|
50723
|
+
headers: { "Content-Type": "application/json" },
|
|
50724
|
+
body: JSON.stringify({ text, room_id: roomId }),
|
|
50725
|
+
signal: options?.signal
|
|
50726
|
+
});
|
|
50727
|
+
if (!res.ok) {
|
|
50728
|
+
const body = await res.text().catch(() => "");
|
|
50729
|
+
return { ok: false, error: `HTTP ${res.status}${body ? `: ${body}` : ""}` };
|
|
50730
|
+
}
|
|
50731
|
+
const data = await res.json();
|
|
50732
|
+
return { ok: data.ok ?? true };
|
|
50733
|
+
} catch (err) {
|
|
50734
|
+
return { ok: false, error: friendlyError(err) };
|
|
50735
|
+
}
|
|
50736
|
+
}
|
|
50737
|
+
async function sendToTarget(target, text, options) {
|
|
50738
|
+
if (typeof text !== "string" || text.trim().length === 0) {
|
|
50739
|
+
return { ok: false, error: "Message text must be a non-empty string" };
|
|
50740
|
+
}
|
|
50741
|
+
requestHeartbeatNow({ reason: "proactive-target-send" }).catch(() => {
|
|
50742
|
+
});
|
|
50743
|
+
try {
|
|
50744
|
+
const base = resolveBaseUrl(options);
|
|
50745
|
+
const sendPath = process.env.OPENCLAW_GATEWAY_URL ? "/agentvault/send" : "/send";
|
|
50746
|
+
const body = { text };
|
|
50747
|
+
if (target.startsWith("room:")) {
|
|
50748
|
+
body.room_id = target.slice(5);
|
|
50749
|
+
} else if (target.startsWith("a2a:")) {
|
|
50750
|
+
body.hub_address = target.slice(4);
|
|
50751
|
+
} else if (target === "context") {
|
|
50752
|
+
body.target = "context";
|
|
50753
|
+
}
|
|
50754
|
+
const res = await fetch(`${base}${sendPath}`, {
|
|
50755
|
+
method: "POST",
|
|
50756
|
+
headers: { "Content-Type": "application/json" },
|
|
50757
|
+
body: JSON.stringify(body),
|
|
50758
|
+
signal: options?.signal
|
|
50759
|
+
});
|
|
50760
|
+
if (!res.ok) {
|
|
50761
|
+
const respBody = await res.text().catch(() => "");
|
|
50762
|
+
return { ok: false, error: `HTTP ${res.status}${respBody ? `: ${respBody}` : ""}` };
|
|
50763
|
+
}
|
|
50764
|
+
const data = await res.json();
|
|
50765
|
+
return {
|
|
50766
|
+
ok: data.ok ?? true,
|
|
50767
|
+
destination: data.destination
|
|
50768
|
+
};
|
|
50769
|
+
} catch (err) {
|
|
50770
|
+
return { ok: false, error: friendlyError(err) };
|
|
50771
|
+
}
|
|
50772
|
+
}
|
|
50773
|
+
async function listTargets(options) {
|
|
50774
|
+
try {
|
|
50775
|
+
const base = resolveBaseUrl(options);
|
|
50776
|
+
const targetsPath = process.env.OPENCLAW_GATEWAY_URL ? "/agentvault/targets" : "/targets";
|
|
50777
|
+
const res = await fetch(`${base}${targetsPath}`, { signal: options?.signal });
|
|
50778
|
+
if (!res.ok) {
|
|
50779
|
+
return { ok: false, error: `HTTP ${res.status}` };
|
|
50780
|
+
}
|
|
50781
|
+
const data = await res.json();
|
|
50782
|
+
return {
|
|
50783
|
+
ok: true,
|
|
50784
|
+
targets: data.targets,
|
|
50785
|
+
context: data.context
|
|
50786
|
+
};
|
|
50787
|
+
} catch (err) {
|
|
50788
|
+
return { ok: false, error: friendlyError(err) };
|
|
50789
|
+
}
|
|
50790
|
+
}
|
|
50411
50791
|
async function checkGateway(options) {
|
|
50412
50792
|
try {
|
|
50413
50793
|
const base = resolveBaseUrl(options);
|
|
@@ -50453,6 +50833,7 @@ var init_openclaw_entry = __esm({
|
|
|
50453
50833
|
init_fetch_interceptor();
|
|
50454
50834
|
init_http_handlers();
|
|
50455
50835
|
init_openclaw_compat();
|
|
50836
|
+
init_types();
|
|
50456
50837
|
isUsingManagedRoutes = false;
|
|
50457
50838
|
}
|
|
50458
50839
|
});
|
|
@@ -51135,7 +51516,7 @@ function createZodEnum(values, params) {
|
|
|
51135
51516
|
});
|
|
51136
51517
|
}
|
|
51137
51518
|
var ParseInputLazyPath, handleResult, ZodType, cuidRegex, cuid2Regex, ulidRegex, uuidRegex, nanoidRegex, jwtRegex, durationRegex, emailRegex, _emojiRegex, emojiRegex, ipv4Regex, ipv4CidrRegex, ipv6Regex, ipv6CidrRegex, base64Regex, base64urlRegex, dateRegexSource, dateRegex, ZodString, ZodNumber, ZodBigInt, ZodBoolean, ZodDate, ZodSymbol, ZodUndefined, ZodNull, ZodAny, ZodUnknown, ZodNever, ZodVoid, ZodArray, ZodObject, ZodUnion, getDiscriminator, ZodDiscriminatedUnion, ZodIntersection, ZodTuple, ZodRecord, ZodMap, ZodSet, ZodFunction, ZodLazy, ZodLiteral, ZodEnum, ZodNativeEnum, ZodPromise, ZodEffects, ZodOptional, ZodNullable, ZodDefault, ZodCatch, ZodNaN, ZodBranded, ZodPipeline, ZodReadonly, late, ZodFirstPartyTypeKind, stringType, numberType, nanType, bigIntType, booleanType, dateType, symbolType, undefinedType, nullType, anyType, unknownType, neverType, voidType, arrayType, objectType, strictObjectType, unionType, discriminatedUnionType, intersectionType, tupleType, recordType, mapType, setType, functionType, lazyType, literalType, enumType, nativeEnumType, promiseType, effectsType, optionalType, nullableType, preprocessType, pipelineType;
|
|
51138
|
-
var
|
|
51519
|
+
var init_types2 = __esm({
|
|
51139
51520
|
"../../node_modules/zod/v3/types.js"() {
|
|
51140
51521
|
init_ZodError();
|
|
51141
51522
|
init_errors();
|
|
@@ -54387,7 +54768,7 @@ var init_external = __esm({
|
|
|
54387
54768
|
init_parseUtil();
|
|
54388
54769
|
init_typeAliases();
|
|
54389
54770
|
init_util();
|
|
54390
|
-
|
|
54771
|
+
init_types2();
|
|
54391
54772
|
init_ZodError();
|
|
54392
54773
|
}
|
|
54393
54774
|
});
|
|
@@ -62159,7 +62540,7 @@ function assertCompleteRequestResourceTemplate(request) {
|
|
|
62159
62540
|
void request;
|
|
62160
62541
|
}
|
|
62161
62542
|
var LATEST_PROTOCOL_VERSION, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, JSONRPC_VERSION, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskCreationParamsSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, isInitializeRequest, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, McpError, UrlElicitationRequiredError;
|
|
62162
|
-
var
|
|
62543
|
+
var init_types3 = __esm({
|
|
62163
62544
|
"../../node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"() {
|
|
62164
62545
|
init_v4();
|
|
62165
62546
|
LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
@@ -65325,7 +65706,7 @@ var DEFAULT_REQUEST_TIMEOUT_MSEC, Protocol;
|
|
|
65325
65706
|
var init_protocol = __esm({
|
|
65326
65707
|
"../../node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js"() {
|
|
65327
65708
|
init_zod_compat();
|
|
65328
|
-
|
|
65709
|
+
init_types3();
|
|
65329
65710
|
init_interfaces();
|
|
65330
65711
|
init_zod_json_schema_compat();
|
|
65331
65712
|
DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
@@ -73221,7 +73602,7 @@ var Server;
|
|
|
73221
73602
|
var init_server2 = __esm({
|
|
73222
73603
|
"../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js"() {
|
|
73223
73604
|
init_protocol();
|
|
73224
|
-
|
|
73605
|
+
init_types3();
|
|
73225
73606
|
init_ajv_provider();
|
|
73226
73607
|
init_zod_compat();
|
|
73227
73608
|
init_server();
|
|
@@ -73791,7 +74172,7 @@ var init_mcp = __esm({
|
|
|
73791
74172
|
init_server2();
|
|
73792
74173
|
init_zod_compat();
|
|
73793
74174
|
init_zod_json_schema_compat();
|
|
73794
|
-
|
|
74175
|
+
init_types3();
|
|
73795
74176
|
init_completable();
|
|
73796
74177
|
init_uriTemplate();
|
|
73797
74178
|
init_toolNameValidation();
|
|
@@ -75063,7 +75444,7 @@ var init_dist2 = __esm({
|
|
|
75063
75444
|
var WebStandardStreamableHTTPServerTransport;
|
|
75064
75445
|
var init_webStandardStreamableHttp = __esm({
|
|
75065
75446
|
"../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js"() {
|
|
75066
|
-
|
|
75447
|
+
init_types3();
|
|
75067
75448
|
WebStandardStreamableHTTPServerTransport = class {
|
|
75068
75449
|
constructor(options = {}) {
|
|
75069
75450
|
this._started = false;
|
|
@@ -75806,7 +76187,13 @@ var init_mcp_server2 = __esm({
|
|
|
75806
76187
|
tags: s2.tags,
|
|
75807
76188
|
sla: s2.slaDefinition,
|
|
75808
76189
|
hasSchema: !!s2.inputSchema,
|
|
75809
|
-
hasInstructions: !!s2.instructions
|
|
76190
|
+
hasInstructions: !!s2.instructions,
|
|
76191
|
+
certificationTier: s2.certificationTier,
|
|
76192
|
+
modelRouting: s2.modelRouting,
|
|
76193
|
+
allowedModels: s2.allowedModels,
|
|
76194
|
+
hasToolPolicy: !!(s2.toolsAllowed || s2.toolsDenied),
|
|
76195
|
+
hasOutputSchema: !!s2.outputSchema,
|
|
76196
|
+
requiredPolicies: s2.requiredPolicies
|
|
75810
76197
|
}));
|
|
75811
76198
|
return {
|
|
75812
76199
|
contents: [{
|
|
@@ -76002,7 +76389,7 @@ function parseSkillMd(content) {
|
|
|
76002
76389
|
if (!frontmatter.name) return null;
|
|
76003
76390
|
const instructionLines = lines.slice(endIdx + 1);
|
|
76004
76391
|
const instructions = instructionLines.join("\n").trim();
|
|
76005
|
-
|
|
76392
|
+
const skill = {
|
|
76006
76393
|
name: frontmatter.name,
|
|
76007
76394
|
version: frontmatter.version,
|
|
76008
76395
|
description: frontmatter.description,
|
|
@@ -76011,82 +76398,76 @@ function parseSkillMd(content) {
|
|
|
76011
76398
|
slaDefinition: frontmatter.sla,
|
|
76012
76399
|
instructions: instructions || void 0
|
|
76013
76400
|
};
|
|
76401
|
+
if (frontmatter.agentVault) {
|
|
76402
|
+
const av = frontmatter.agentVault;
|
|
76403
|
+
if (av.certification) skill.certificationTier = av.certification;
|
|
76404
|
+
if (av.runtime?.capabilities) skill.toolsAllowed = av.runtime.capabilities;
|
|
76405
|
+
if (av.runtime?.forbidden) skill.toolsDenied = av.runtime.forbidden;
|
|
76406
|
+
if (av.runtime?.output_schema) skill.outputSchema = av.runtime.output_schema;
|
|
76407
|
+
if (av.model?.routing) skill.modelRouting = av.model.routing;
|
|
76408
|
+
if (av.model?.allowed) skill.allowedModels = av.model.allowed;
|
|
76409
|
+
if (av.model?.default) skill.defaultModel = av.model.default;
|
|
76410
|
+
if (av.integrity) skill.integrity = av.integrity;
|
|
76411
|
+
if (av.requiredPolicies) skill.requiredPolicies = av.requiredPolicies;
|
|
76412
|
+
}
|
|
76413
|
+
return skill;
|
|
76014
76414
|
}
|
|
76015
76415
|
function parseSimpleYaml(yaml) {
|
|
76016
76416
|
const result = {};
|
|
76017
76417
|
const lines = yaml.split("\n");
|
|
76018
|
-
|
|
76019
|
-
let
|
|
76020
|
-
|
|
76418
|
+
const stack = [];
|
|
76419
|
+
let currentObj = result;
|
|
76420
|
+
function parseValue(raw) {
|
|
76421
|
+
const value = raw.replace(/^["']|["']$/g, "");
|
|
76422
|
+
const num = Number(value);
|
|
76423
|
+
if (!isNaN(num) && value !== "") return num;
|
|
76424
|
+
if (value === "true") return true;
|
|
76425
|
+
if (value === "false") return false;
|
|
76426
|
+
return value;
|
|
76427
|
+
}
|
|
76021
76428
|
for (const line of lines) {
|
|
76022
76429
|
const trimmed = line.trim();
|
|
76023
76430
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
76024
76431
|
const indent = line.length - line.trimStart().length;
|
|
76025
|
-
|
|
76432
|
+
while (stack.length > 0 && indent <= stack[stack.length - 1].indent) {
|
|
76433
|
+
const popped = stack.pop();
|
|
76434
|
+
currentObj = stack.length > 0 ? stack[stack.length - 1].obj : result;
|
|
76435
|
+
currentObj[popped.key] = popped.obj;
|
|
76436
|
+
}
|
|
76437
|
+
const inlineArrayMatch = trimmed.match(/^(\w[\w_-]*)\s*:\s*\[(.+)\]$/);
|
|
76026
76438
|
if (inlineArrayMatch) {
|
|
76027
76439
|
const key = inlineArrayMatch[1];
|
|
76028
76440
|
const values = inlineArrayMatch[2].split(",").map((v2) => v2.trim().replace(/^["']|["']$/g, ""));
|
|
76029
|
-
if (
|
|
76030
|
-
|
|
76441
|
+
if (stack.length > 0) {
|
|
76442
|
+
stack[stack.length - 1].obj[key] = values;
|
|
76031
76443
|
} else {
|
|
76032
|
-
|
|
76033
|
-
result[currentKey] = nestedObj;
|
|
76034
|
-
nestedObj = null;
|
|
76035
|
-
}
|
|
76036
|
-
result[key] = values;
|
|
76444
|
+
currentObj[key] = values;
|
|
76037
76445
|
}
|
|
76038
76446
|
continue;
|
|
76039
76447
|
}
|
|
76040
|
-
const kvMatch = trimmed.match(/^(\w[\
|
|
76041
|
-
if (kvMatch
|
|
76042
|
-
if (nestedObj && currentKey) {
|
|
76043
|
-
result[currentKey] = nestedObj;
|
|
76044
|
-
nestedObj = null;
|
|
76045
|
-
}
|
|
76448
|
+
const kvMatch = trimmed.match(/^(\w[\w_-]*)\s*:\s*(.+)$/);
|
|
76449
|
+
if (kvMatch) {
|
|
76046
76450
|
const key = kvMatch[1];
|
|
76047
|
-
const
|
|
76048
|
-
|
|
76049
|
-
|
|
76050
|
-
result[key] = num;
|
|
76051
|
-
} else if (value === "true") {
|
|
76052
|
-
result[key] = true;
|
|
76053
|
-
} else if (value === "false") {
|
|
76054
|
-
result[key] = false;
|
|
76451
|
+
const val = parseValue(kvMatch[2]);
|
|
76452
|
+
if (stack.length > 0) {
|
|
76453
|
+
stack[stack.length - 1].obj[key] = val;
|
|
76055
76454
|
} else {
|
|
76056
|
-
|
|
76455
|
+
currentObj[key] = val;
|
|
76057
76456
|
}
|
|
76058
76457
|
continue;
|
|
76059
76458
|
}
|
|
76060
|
-
const nestedMatch = trimmed.match(/^(\w[\
|
|
76061
|
-
if (nestedMatch
|
|
76062
|
-
|
|
76063
|
-
|
|
76064
|
-
}
|
|
76065
|
-
currentKey = nestedMatch[1];
|
|
76066
|
-
currentIndent = indent;
|
|
76067
|
-
nestedObj = {};
|
|
76459
|
+
const nestedMatch = trimmed.match(/^(\w[\w_-]*)\s*:$/);
|
|
76460
|
+
if (nestedMatch) {
|
|
76461
|
+
const key = nestedMatch[1];
|
|
76462
|
+
const newObj = {};
|
|
76463
|
+
stack.push({ key, obj: newObj, indent });
|
|
76068
76464
|
continue;
|
|
76069
76465
|
}
|
|
76070
|
-
if (nestedObj && indent > 0) {
|
|
76071
|
-
const nestedKv = trimmed.match(/^(\w[\w-]*)\s*:\s*(.+)$/);
|
|
76072
|
-
if (nestedKv) {
|
|
76073
|
-
const key = nestedKv[1];
|
|
76074
|
-
const value = nestedKv[2].replace(/^["']|["']$/g, "");
|
|
76075
|
-
const num = Number(value);
|
|
76076
|
-
if (!isNaN(num) && value !== "") {
|
|
76077
|
-
nestedObj[key] = num;
|
|
76078
|
-
} else if (value === "true") {
|
|
76079
|
-
nestedObj[key] = true;
|
|
76080
|
-
} else if (value === "false") {
|
|
76081
|
-
nestedObj[key] = false;
|
|
76082
|
-
} else {
|
|
76083
|
-
nestedObj[key] = value;
|
|
76084
|
-
}
|
|
76085
|
-
}
|
|
76086
|
-
}
|
|
76087
76466
|
}
|
|
76088
|
-
|
|
76089
|
-
|
|
76467
|
+
while (stack.length > 0) {
|
|
76468
|
+
const popped = stack.pop();
|
|
76469
|
+
const parent = stack.length > 0 ? stack[stack.length - 1].obj : result;
|
|
76470
|
+
parent[popped.key] = popped.obj;
|
|
76090
76471
|
}
|
|
76091
76472
|
return result;
|
|
76092
76473
|
}
|
|
@@ -76358,11 +76739,157 @@ var init_skill_telemetry = __esm({
|
|
|
76358
76739
|
}
|
|
76359
76740
|
});
|
|
76360
76741
|
|
|
76742
|
+
// src/policy-enforcer.ts
|
|
76743
|
+
var PolicyEnforcer;
|
|
76744
|
+
var init_policy_enforcer = __esm({
|
|
76745
|
+
async "src/policy-enforcer.ts"() {
|
|
76746
|
+
"use strict";
|
|
76747
|
+
await init_dist();
|
|
76748
|
+
PolicyEnforcer = class {
|
|
76749
|
+
skills = /* @__PURE__ */ new Map();
|
|
76750
|
+
metrics = {
|
|
76751
|
+
totalEvaluations: 0,
|
|
76752
|
+
totalBlocks: 0,
|
|
76753
|
+
totalWarnings: 0,
|
|
76754
|
+
bySkill: {},
|
|
76755
|
+
byRule: {}
|
|
76756
|
+
};
|
|
76757
|
+
spanBuffer = [];
|
|
76758
|
+
/**
|
|
76759
|
+
* Register a skill definition for policy evaluation.
|
|
76760
|
+
*/
|
|
76761
|
+
registerSkill(skill) {
|
|
76762
|
+
this.skills.set(skill.name, skill);
|
|
76763
|
+
}
|
|
76764
|
+
/**
|
|
76765
|
+
* Full 5-stage policy pipeline evaluation.
|
|
76766
|
+
*/
|
|
76767
|
+
evaluate(ctx) {
|
|
76768
|
+
this.metrics.totalEvaluations++;
|
|
76769
|
+
const skillMetrics = this.metrics.bySkill[ctx.skillName] ??= { evaluations: 0, blocks: 0 };
|
|
76770
|
+
skillMetrics.evaluations++;
|
|
76771
|
+
const violations = [];
|
|
76772
|
+
const skill = this.skills.get(ctx.skillName);
|
|
76773
|
+
if (skill) {
|
|
76774
|
+
if (ctx.toolName && skill.toolsDenied?.length) {
|
|
76775
|
+
if (skill.toolsDenied.includes(ctx.toolName)) {
|
|
76776
|
+
violations.push({
|
|
76777
|
+
ruleId: `deny:${ctx.skillName}:${ctx.toolName}`,
|
|
76778
|
+
scope: "tool",
|
|
76779
|
+
action: "block",
|
|
76780
|
+
type: "forbidden_tool",
|
|
76781
|
+
message: `Tool "${ctx.toolName}" is forbidden for skill "${ctx.skillName}"`
|
|
76782
|
+
});
|
|
76783
|
+
}
|
|
76784
|
+
}
|
|
76785
|
+
if (ctx.toolName && skill.toolsAllowed?.length) {
|
|
76786
|
+
if (!skill.toolsAllowed.includes(ctx.toolName)) {
|
|
76787
|
+
violations.push({
|
|
76788
|
+
ruleId: `allow:${ctx.skillName}:${ctx.toolName}`,
|
|
76789
|
+
scope: "tool",
|
|
76790
|
+
action: "block",
|
|
76791
|
+
type: "tool_not_allowed",
|
|
76792
|
+
message: `Tool "${ctx.toolName}" is not in the allowed list for skill "${ctx.skillName}"`
|
|
76793
|
+
});
|
|
76794
|
+
}
|
|
76795
|
+
}
|
|
76796
|
+
if (ctx.model && skill.allowedModels?.length) {
|
|
76797
|
+
if (!skill.allowedModels.includes(ctx.model)) {
|
|
76798
|
+
violations.push({
|
|
76799
|
+
ruleId: `model:${ctx.skillName}:${ctx.model}`,
|
|
76800
|
+
scope: "model",
|
|
76801
|
+
action: "block",
|
|
76802
|
+
type: "model_not_allowed",
|
|
76803
|
+
message: `Model "${ctx.model}" is not allowed for skill "${ctx.skillName}". Allowed: ${skill.allowedModels.join(", ")}`
|
|
76804
|
+
});
|
|
76805
|
+
}
|
|
76806
|
+
}
|
|
76807
|
+
}
|
|
76808
|
+
const blocked = violations.some((v2) => v2.action === "block");
|
|
76809
|
+
for (const v2 of violations) {
|
|
76810
|
+
this.metrics.byRule[v2.ruleId] = (this.metrics.byRule[v2.ruleId] ?? 0) + 1;
|
|
76811
|
+
if (v2.action === "block") this.metrics.totalBlocks++;
|
|
76812
|
+
if (v2.action === "warn") this.metrics.totalWarnings++;
|
|
76813
|
+
this.spanBuffer.push(
|
|
76814
|
+
buildPolicyViolationSpan({
|
|
76815
|
+
ruleId: v2.ruleId,
|
|
76816
|
+
policyScope: v2.scope,
|
|
76817
|
+
actionTaken: v2.action,
|
|
76818
|
+
violationType: v2.type,
|
|
76819
|
+
targetTool: ctx.toolName,
|
|
76820
|
+
targetModel: ctx.model,
|
|
76821
|
+
skillName: ctx.skillName
|
|
76822
|
+
})
|
|
76823
|
+
);
|
|
76824
|
+
}
|
|
76825
|
+
if (blocked) {
|
|
76826
|
+
skillMetrics.blocks++;
|
|
76827
|
+
}
|
|
76828
|
+
return {
|
|
76829
|
+
allowed: !blocked,
|
|
76830
|
+
violations,
|
|
76831
|
+
stage: "report"
|
|
76832
|
+
};
|
|
76833
|
+
}
|
|
76834
|
+
/**
|
|
76835
|
+
* Wrap an MCP tool handler with policy enforcement.
|
|
76836
|
+
* Returns a function that checks policy before calling the original handler.
|
|
76837
|
+
*/
|
|
76838
|
+
wrapHandler(skillName, handler) {
|
|
76839
|
+
return async (args) => {
|
|
76840
|
+
const result = this.evaluate({
|
|
76841
|
+
skillName,
|
|
76842
|
+
args
|
|
76843
|
+
});
|
|
76844
|
+
if (!result.allowed) {
|
|
76845
|
+
return {
|
|
76846
|
+
blocked: true,
|
|
76847
|
+
violations: result.violations.map((v2) => ({
|
|
76848
|
+
rule: v2.ruleId,
|
|
76849
|
+
reason: v2.message,
|
|
76850
|
+
scope: v2.scope
|
|
76851
|
+
}))
|
|
76852
|
+
};
|
|
76853
|
+
}
|
|
76854
|
+
return handler(args);
|
|
76855
|
+
};
|
|
76856
|
+
}
|
|
76857
|
+
/**
|
|
76858
|
+
* Get accumulated policy metrics.
|
|
76859
|
+
*/
|
|
76860
|
+
getMetrics() {
|
|
76861
|
+
return { ...this.metrics };
|
|
76862
|
+
}
|
|
76863
|
+
/**
|
|
76864
|
+
* Drain buffered telemetry spans.
|
|
76865
|
+
*/
|
|
76866
|
+
drainSpans() {
|
|
76867
|
+
const spans = this.spanBuffer;
|
|
76868
|
+
this.spanBuffer = [];
|
|
76869
|
+
return spans;
|
|
76870
|
+
}
|
|
76871
|
+
/**
|
|
76872
|
+
* Reset all metrics (for testing).
|
|
76873
|
+
*/
|
|
76874
|
+
resetMetrics() {
|
|
76875
|
+
this.metrics = {
|
|
76876
|
+
totalEvaluations: 0,
|
|
76877
|
+
totalBlocks: 0,
|
|
76878
|
+
totalWarnings: 0,
|
|
76879
|
+
bySkill: {},
|
|
76880
|
+
byRule: {}
|
|
76881
|
+
};
|
|
76882
|
+
}
|
|
76883
|
+
};
|
|
76884
|
+
}
|
|
76885
|
+
});
|
|
76886
|
+
|
|
76361
76887
|
// src/index.ts
|
|
76362
76888
|
var VERSION;
|
|
76363
76889
|
var init_index = __esm({
|
|
76364
76890
|
async "src/index.ts"() {
|
|
76365
76891
|
await init_channel();
|
|
76892
|
+
init_types();
|
|
76366
76893
|
init_account_config();
|
|
76367
76894
|
await init_openclaw_plugin();
|
|
76368
76895
|
init_gateway_send();
|
|
@@ -76374,12 +76901,14 @@ var init_index = __esm({
|
|
|
76374
76901
|
init_skill_manifest();
|
|
76375
76902
|
init_skill_invoker();
|
|
76376
76903
|
await init_skill_telemetry();
|
|
76904
|
+
await init_policy_enforcer();
|
|
76377
76905
|
VERSION = "0.14.1";
|
|
76378
76906
|
}
|
|
76379
76907
|
});
|
|
76380
76908
|
await init_index();
|
|
76381
76909
|
export {
|
|
76382
76910
|
AgentVaultMcpServer,
|
|
76911
|
+
PolicyEnforcer,
|
|
76383
76912
|
SecureChannel,
|
|
76384
76913
|
VERSION,
|
|
76385
76914
|
agentVaultPlugin,
|
|
@@ -76392,20 +76921,25 @@ export {
|
|
|
76392
76921
|
handleDecisionRequest,
|
|
76393
76922
|
handleSendRequest,
|
|
76394
76923
|
handleStatusRequest,
|
|
76924
|
+
handleTargetsRequest,
|
|
76395
76925
|
invokeSkill,
|
|
76396
76926
|
isUsingManagedRoutes,
|
|
76397
76927
|
listAccountIds,
|
|
76928
|
+
listTargets,
|
|
76398
76929
|
loadSkillsFromApi,
|
|
76399
76930
|
loadSkillsFromDirectory,
|
|
76400
76931
|
mergeSkills,
|
|
76401
76932
|
onAgentEvent,
|
|
76402
76933
|
onSessionTranscriptUpdate,
|
|
76403
76934
|
parseSkillMd,
|
|
76935
|
+
parseTarget,
|
|
76404
76936
|
reportSkillInvocation,
|
|
76405
76937
|
requestHeartbeatNow,
|
|
76406
76938
|
resolveAccount,
|
|
76407
76939
|
sendDecisionToOwner,
|
|
76408
76940
|
sendToOwner,
|
|
76941
|
+
sendToRoom,
|
|
76942
|
+
sendToTarget,
|
|
76409
76943
|
setOcRuntime,
|
|
76410
76944
|
wrapSkillExecution
|
|
76411
76945
|
};
|