@axonflow/openclaw 1.3.2 → 2.0.1
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/CHANGELOG.md +71 -0
- package/README.md +111 -7
- package/dist/audit.d.ts +2 -2
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +2 -2
- package/dist/audit.js.map +1 -1
- package/dist/axonflow-client.d.ts +22 -0
- package/dist/axonflow-client.d.ts.map +1 -1
- package/dist/axonflow-client.js +56 -0
- package/dist/axonflow-client.js.map +1 -1
- package/dist/cache-dir.d.ts +34 -0
- package/dist/cache-dir.d.ts.map +1 -0
- package/dist/cache-dir.js +106 -0
- package/dist/cache-dir.js.map +1 -0
- package/dist/client-ref.d.ts +19 -0
- package/dist/client-ref.d.ts.map +1 -0
- package/dist/client-ref.js +16 -0
- package/dist/client-ref.js.map +1 -0
- package/dist/community-saas-bootstrap.d.ts +85 -0
- package/dist/community-saas-bootstrap.d.ts.map +1 -0
- package/dist/community-saas-bootstrap.js +256 -0
- package/dist/community-saas-bootstrap.js.map +1 -0
- package/dist/community-saas-context.d.ts +82 -0
- package/dist/community-saas-context.d.ts.map +1 -0
- package/dist/community-saas-context.js +196 -0
- package/dist/community-saas-context.js.map +1 -0
- package/dist/config.d.ts +26 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +60 -30
- package/dist/config.js.map +1 -1
- package/dist/governance.d.ts +3 -2
- package/dist/governance.d.ts.map +1 -1
- package/dist/governance.js +2 -2
- package/dist/governance.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -12
- package/dist/index.js.map +1 -1
- package/dist/llm-audit.d.ts +3 -3
- package/dist/llm-audit.d.ts.map +1 -1
- package/dist/llm-audit.js +3 -3
- package/dist/llm-audit.js.map +1 -1
- package/dist/message-guard.d.ts +2 -2
- package/dist/message-guard.d.ts.map +1 -1
- package/dist/message-guard.js +2 -2
- package/dist/message-guard.js.map +1 -1
- package/dist/plugin-version-check.d.ts +50 -0
- package/dist/plugin-version-check.d.ts.map +1 -0
- package/dist/plugin-version-check.js +89 -0
- package/dist/plugin-version-check.js.map +1 -0
- package/dist/telemetry-config.d.ts +5 -3
- package/dist/telemetry-config.d.ts.map +1 -1
- package/dist/telemetry-config.js +1 -15
- package/dist/telemetry-config.js.map +1 -1
- package/dist/telemetry-context.d.ts +65 -0
- package/dist/telemetry-context.d.ts.map +1 -0
- package/dist/telemetry-context.js +116 -0
- package/dist/telemetry-context.js.map +1 -0
- package/dist/telemetry.d.ts +42 -18
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +113 -54
- package/dist/telemetry.js.map +1 -1
- package/openclaw.plugin.json +60 -6
- package/package.json +10 -5
package/dist/telemetry.js
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Anonymous usage telemetry
|
|
2
|
+
* Anonymous usage telemetry — 7-day heartbeat (TypeScript).
|
|
3
3
|
*
|
|
4
|
-
* Sends
|
|
5
|
-
*
|
|
6
|
-
* and OpenClaw version. No PII, no tool arguments, no policy data.
|
|
4
|
+
* Sends an anonymous POST to checkpoint.getaxonflow.com on plugin
|
|
5
|
+
* initialization, at most once every 7 days per machine.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* after
|
|
11
|
-
*
|
|
7
|
+
* Design rules (per feedback_telemetry_heartbeat_design_rules.md):
|
|
8
|
+
* 1. Stamp-on-delivery, not stamp-on-attempt. Stamp file mtime
|
|
9
|
+
* advances ONLY after the HTTP POST returns 2xx. A transient
|
|
10
|
+
* network failure does not silence telemetry for 7 days.
|
|
11
|
+
* 2. In-flight gate via a per-process Promise. Concurrent plugin
|
|
12
|
+
* loads do not race to send duplicate pings.
|
|
13
|
+
* 3. Opt-out check FIRST, before any rate-limit or filesystem ops.
|
|
14
|
+
* AXONFLOW_TELEMETRY=off is re-evaluated every call.
|
|
15
|
+
* 4. mtime as the freshness source; stamp body holds instance_id.
|
|
16
|
+
* 5. Atomic stamp write: tmp + rename.
|
|
17
|
+
* 6. Persistent instance_id across heartbeats.
|
|
18
|
+
* 7. Defensive against future-dated stamps (clock skew → treat absent).
|
|
19
|
+
* 8. Cross-platform cache dir resolution (cache-dir.ts).
|
|
12
20
|
*
|
|
13
|
-
* Configuration resolution (opt-out flags
|
|
14
|
-
* telemetry-config.ts
|
|
21
|
+
* Configuration resolution (opt-out flags, checkpoint URL) lives in
|
|
22
|
+
* telemetry-config.ts. Environment + filesystem reads (harness probe
|
|
23
|
+
* endpoint, stamp inspection, atomic stamp write) live in
|
|
24
|
+
* telemetry-context.ts. This module is the network-only side of the
|
|
25
|
+
* heartbeat: it imports plain values from the context modules and only
|
|
26
|
+
* issues HTTP requests.
|
|
15
27
|
*/
|
|
28
|
+
import { axonflowCacheDir } from "./cache-dir.js";
|
|
16
29
|
import { loadTelemetryConfig } from "./telemetry-config.js";
|
|
30
|
+
import { captureRuntimeInfo, ensureCacheDir, readStampMetadata, resolveProbeEndpoint, stampPath, writeStampAtomic, } from "./telemetry-context.js";
|
|
17
31
|
const TELEMETRY_TIMEOUT_MS = 3000;
|
|
32
|
+
const HEARTBEAT_INTERVAL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
33
|
+
let inFlight = null;
|
|
18
34
|
function generateInstanceId() {
|
|
19
35
|
try {
|
|
20
|
-
if (typeof crypto !== "undefined" &&
|
|
21
|
-
typeof crypto.randomUUID === "function") {
|
|
36
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
22
37
|
return crypto.randomUUID();
|
|
23
38
|
}
|
|
24
39
|
}
|
|
@@ -31,9 +46,6 @@ function generateInstanceId() {
|
|
|
31
46
|
return v.toString(16);
|
|
32
47
|
});
|
|
33
48
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Detect the AxonFlow platform version via /health endpoint.
|
|
36
|
-
*/
|
|
37
49
|
async function detectPlatformVersion(endpoint) {
|
|
38
50
|
const controller = new AbortController();
|
|
39
51
|
const timeoutId = setTimeout(() => controller.abort(), 2000);
|
|
@@ -46,9 +58,7 @@ async function detectPlatformVersion(endpoint) {
|
|
|
46
58
|
if (!resp.ok)
|
|
47
59
|
return null;
|
|
48
60
|
const body = (await resp.json());
|
|
49
|
-
return typeof body.version === "string" && body.version
|
|
50
|
-
? body.version
|
|
51
|
-
: null;
|
|
61
|
+
return typeof body.version === "string" && body.version ? body.version : null;
|
|
52
62
|
}
|
|
53
63
|
catch {
|
|
54
64
|
clearTimeout(timeoutId);
|
|
@@ -56,63 +66,112 @@ async function detectPlatformVersion(endpoint) {
|
|
|
56
66
|
}
|
|
57
67
|
}
|
|
58
68
|
/**
|
|
59
|
-
* Send an anonymous telemetry
|
|
69
|
+
* Send an anonymous telemetry heartbeat. Concurrent calls are de-duplicated
|
|
70
|
+
* via a per-process in-flight gate; the second concurrent caller awaits the
|
|
71
|
+
* first's promise rather than firing a duplicate.
|
|
60
72
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
73
|
+
* Returns a promise that resolves when the heartbeat completes (success,
|
|
74
|
+
* skip, or failure). Production callers should treat as fire-and-forget;
|
|
75
|
+
* tests can await for assertions.
|
|
63
76
|
*/
|
|
64
77
|
export function sendTelemetryPing(options) {
|
|
78
|
+
if (inFlight) {
|
|
79
|
+
return inFlight;
|
|
80
|
+
}
|
|
81
|
+
inFlight = sendInner(options).finally(() => {
|
|
82
|
+
inFlight = null;
|
|
83
|
+
});
|
|
84
|
+
return inFlight;
|
|
85
|
+
}
|
|
86
|
+
async function sendInner(options) {
|
|
87
|
+
// 1. Opt-out check FIRST.
|
|
65
88
|
const config = loadTelemetryConfig();
|
|
66
89
|
if (config.optedOut) {
|
|
67
90
|
return;
|
|
68
91
|
}
|
|
69
|
-
|
|
70
|
-
|
|
92
|
+
// 2. Resolve the stamp file location and ensure the cache dir is private.
|
|
93
|
+
const cacheDir = ensureCacheDir(axonflowCacheDir());
|
|
94
|
+
const stampFile = stampPath(cacheDir);
|
|
95
|
+
const now = options.now ?? (() => new Date());
|
|
96
|
+
const nowMs = now().getTime();
|
|
97
|
+
// 3. mtime check, defensive against future-dated stamps. The stamp read
|
|
98
|
+
// is done in telemetry-context.ts so this module stays free of fs
|
|
99
|
+
// read calls co-located with fetch.
|
|
100
|
+
const stamp = readStampMetadata(stampFile);
|
|
101
|
+
if (stamp.exists && stamp.mtimeMs > 0 && stamp.mtimeMs <= nowMs) {
|
|
102
|
+
const age = nowMs - stamp.mtimeMs;
|
|
103
|
+
if (age < HEARTBEAT_INTERVAL_MS) {
|
|
104
|
+
return; // fresh — skip
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const priorInstanceId = stamp.priorInstanceId;
|
|
108
|
+
const instanceId = priorInstanceId && /^[a-f0-9-]{8,64}$/i.test(priorInstanceId)
|
|
109
|
+
? priorInstanceId
|
|
110
|
+
: generateInstanceId();
|
|
111
|
+
// 4. Detect platform version (best-effort). The harness override is
|
|
112
|
+
// resolved in telemetry-context.ts so AXONFLOW_HARNESS env reads do
|
|
113
|
+
// not co-locate with fetch in this file.
|
|
114
|
+
const probeEndpoint = resolveProbeEndpoint(options.endpoint);
|
|
115
|
+
let platformVersion = null;
|
|
116
|
+
try {
|
|
117
|
+
platformVersion = await detectPlatformVersion(probeEndpoint);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
platformVersion = null;
|
|
71
121
|
}
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
const runtime = captureRuntimeInfo();
|
|
123
|
+
// Community-SaaS users are first-class for analytics; classifying them as
|
|
124
|
+
// "production" (because plugin-generated auth is present) hides them inside
|
|
125
|
+
// the self-hosted bucket. Surface them explicitly here.
|
|
126
|
+
const deploymentMode = options.mode === "community-saas"
|
|
127
|
+
? "community-saas"
|
|
128
|
+
: options.onError === "block"
|
|
129
|
+
? "production"
|
|
130
|
+
: "development";
|
|
74
131
|
const payload = {
|
|
75
132
|
sdk: "openclaw-plugin",
|
|
76
133
|
sdk_version: options.pluginVersion,
|
|
77
|
-
platform_version:
|
|
78
|
-
os:
|
|
79
|
-
arch:
|
|
80
|
-
runtime_version:
|
|
81
|
-
deployment_mode:
|
|
134
|
+
platform_version: platformVersion,
|
|
135
|
+
os: runtime.os,
|
|
136
|
+
arch: runtime.arch,
|
|
137
|
+
runtime_version: runtime.runtimeVersion,
|
|
138
|
+
deployment_mode: deploymentMode,
|
|
82
139
|
features: [
|
|
83
140
|
`hooks:${options.hookCount}`,
|
|
84
141
|
`high_risk_tools:${options.highRiskToolCount}`,
|
|
85
142
|
`on_error:${options.onError}`,
|
|
143
|
+
`mode:${options.mode}`,
|
|
86
144
|
],
|
|
87
|
-
instance_id:
|
|
145
|
+
instance_id: instanceId,
|
|
88
146
|
};
|
|
147
|
+
// 5. Fire the heartbeat.
|
|
148
|
+
const controller = new AbortController();
|
|
149
|
+
const timeoutId = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
|
|
150
|
+
let delivered = false;
|
|
89
151
|
try {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Silent — platform version remains null
|
|
96
|
-
}
|
|
97
|
-
const controller = new AbortController();
|
|
98
|
-
const timeoutId = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
|
|
99
|
-
try {
|
|
100
|
-
await fetch(config.checkpointUrl, {
|
|
101
|
-
method: "POST",
|
|
102
|
-
headers: { "Content-Type": "application/json" },
|
|
103
|
-
body: JSON.stringify(payload),
|
|
104
|
-
signal: controller.signal,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
finally {
|
|
108
|
-
clearTimeout(timeoutId);
|
|
109
|
-
}
|
|
110
|
-
})().catch(() => {
|
|
111
|
-
// Silent failure — telemetry should never affect plugin behavior
|
|
152
|
+
const resp = await fetch(config.checkpointUrl, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
headers: { "Content-Type": "application/json" },
|
|
155
|
+
body: JSON.stringify(payload),
|
|
156
|
+
signal: controller.signal,
|
|
112
157
|
});
|
|
158
|
+
delivered = resp.ok;
|
|
113
159
|
}
|
|
114
160
|
catch {
|
|
115
|
-
|
|
161
|
+
delivered = false;
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
clearTimeout(timeoutId);
|
|
116
165
|
}
|
|
166
|
+
// 6. Stamp-on-delivery. The atomic write lives in telemetry-context.ts.
|
|
167
|
+
if (delivered) {
|
|
168
|
+
writeStampAtomic(stampFile, instanceId);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Test-only: clear the in-flight gate between tests.
|
|
173
|
+
*/
|
|
174
|
+
export function _resetTelemetryInFlightForTests() {
|
|
175
|
+
inFlight = null;
|
|
117
176
|
}
|
|
118
177
|
//# sourceMappingURL=telemetry.js.map
|
package/dist/telemetry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "axonflow-governance",
|
|
3
|
+
"envVars": {
|
|
4
|
+
"AXONFLOW_TELEMETRY": {
|
|
5
|
+
"required": false,
|
|
6
|
+
"description": "Set to 'off', '0', 'false', or 'no' to disable the 7-day anonymous telemetry heartbeat. When unset (default), the plugin sends a lightweight ping to checkpoint.getaxonflow.com once every 7 days per machine.",
|
|
7
|
+
"values": ["off", "0", "false", "no"]
|
|
8
|
+
},
|
|
9
|
+
"AXONFLOW_COMMUNITY_SAAS": {
|
|
10
|
+
"required": false,
|
|
11
|
+
"description": "Set to '0', 'false', 'off', or 'no' to disable auto-registration with try.getaxonflow.com Community SaaS. When opted out, configure pluginConfig.endpoint to point at a self-hosted AxonFlow instance — otherwise the plugin loads but cannot enforce policy.",
|
|
12
|
+
"values": ["0", "false", "off", "no"]
|
|
13
|
+
},
|
|
14
|
+
"AXONFLOW_CACHE_DIR": {
|
|
15
|
+
"required": false,
|
|
16
|
+
"description": "Override the per-user cache directory used for telemetry stamps and rate-limit backoffs. Defaults to OS conventions: $XDG_CACHE_HOME/axonflow on Linux, ~/Library/Caches/axonflow on macOS, %LOCALAPPDATA%\\axonflow on Windows."
|
|
17
|
+
},
|
|
18
|
+
"AXONFLOW_CONFIG_DIR": {
|
|
19
|
+
"required": false,
|
|
20
|
+
"description": "Override the per-user config directory used for the Community-SaaS registration file (mode 0o600). Defaults to OS conventions: $XDG_CONFIG_HOME/axonflow on Linux, ~/Library/Application Support/axonflow on macOS, %APPDATA%\\axonflow on Windows."
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"runtimeBehavior": {
|
|
24
|
+
"autoBootstrap": {
|
|
25
|
+
"enabled": true,
|
|
26
|
+
"description": "When pluginConfig.endpoint is unset and AXONFLOW_COMMUNITY_SAAS is not opted out, the plugin POSTs to https://try.getaxonflow.com/api/v1/register on first load to obtain Community-SaaS credentials, persists them at $AXONFLOW_CONFIG_DIR/try-registration.json (mode 0o600), and uses them for subsequent governance calls. The 7-day rotation refresh window keeps tenants from lapsing silently.",
|
|
27
|
+
"optOut": "Set AXONFLOW_COMMUNITY_SAAS=0 OR set pluginConfig.endpoint to a self-hosted AxonFlow instance.",
|
|
28
|
+
"userDisclosure": "First-load disclosure banner emitted via plugin logger (warn level), one time per machine, before the registration POST fires."
|
|
29
|
+
},
|
|
30
|
+
"outboundData": {
|
|
31
|
+
"atGovernanceTime": "Tool name + arguments (before execution) and outbound message bodies (before delivery) are sent to the configured AxonFlow endpoint for policy evaluation and audit. With Community SaaS, the endpoint is try.getaxonflow.com; with self-hosted, traffic stays on your network.",
|
|
32
|
+
"telemetry": "Anonymous 7-day heartbeat to checkpoint.getaxonflow.com containing plugin version, OS, arch, runtime version, deployment mode, hook count, and a per-machine instance_id (UUID v4). No tool inputs, no message bodies, no LLM provider keys.",
|
|
33
|
+
"neverTransmitted": ["LLM provider API keys", "OpenClaw conversation history outside governed tools", "Files outside the OpenClaw runtime"]
|
|
34
|
+
},
|
|
35
|
+
"persistence": {
|
|
36
|
+
"files": [
|
|
37
|
+
{
|
|
38
|
+
"path": "$AXONFLOW_CONFIG_DIR/try-registration.json",
|
|
39
|
+
"mode": "0o600",
|
|
40
|
+
"purpose": "Community-SaaS registration credentials (tenant_id, secret, expires_at). Refused at load time if permissions are not 0o600 on POSIX."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "$AXONFLOW_CONFIG_DIR/openclaw-plugin-community-saas-disclosure-shown",
|
|
44
|
+
"mode": "0o600",
|
|
45
|
+
"purpose": "First-load disclosure stamp. Empty file; presence prevents re-warning on subsequent loads."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"path": "$AXONFLOW_CACHE_DIR/openclaw-plugin-telemetry-sent",
|
|
49
|
+
"mode": "0o600",
|
|
50
|
+
"purpose": "Heartbeat stamp file. Body is the per-machine instance_id (UUID v4); mtime drives the 7-day rate limit."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"path": "$AXONFLOW_CACHE_DIR/openclaw-plugin-register-backoff",
|
|
54
|
+
"mode": "0o600",
|
|
55
|
+
"purpose": "Rate-limit backoff stamp written when /api/v1/register returns 429. Body is a Unix timestamp (seconds) until which the bootstrap will not retry."
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
3
60
|
"uiHints": {
|
|
4
61
|
"endpoint": {
|
|
5
62
|
"label": "AxonFlow Endpoint",
|
|
@@ -52,16 +109,13 @@
|
|
|
52
109
|
"additionalProperties": false,
|
|
53
110
|
"properties": {
|
|
54
111
|
"endpoint": {
|
|
55
|
-
"type": "string"
|
|
56
|
-
"default": "http://localhost:8080"
|
|
112
|
+
"type": "string"
|
|
57
113
|
},
|
|
58
114
|
"clientId": {
|
|
59
|
-
"type": "string"
|
|
60
|
-
"default": "community"
|
|
115
|
+
"type": "string"
|
|
61
116
|
},
|
|
62
117
|
"clientSecret": {
|
|
63
|
-
"type": "string"
|
|
64
|
-
"default": "community"
|
|
118
|
+
"type": "string"
|
|
65
119
|
},
|
|
66
120
|
"highRiskTools": {
|
|
67
121
|
"type": "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axonflow/openclaw",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Policy enforcement, approval gates, and audit trails for OpenClaw — govern tool inputs before execution, scan outbound messages for PII/secrets, and record agent activity for review and compliance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"lint": "eslint src/ tests/",
|
|
27
27
|
"test": "jest",
|
|
28
28
|
"test:coverage": "jest --coverage",
|
|
29
|
+
"scan": "node scripts/scan-tarball.mjs",
|
|
29
30
|
"prepublishOnly": "npm run build"
|
|
30
31
|
},
|
|
31
32
|
"keywords": [
|
|
@@ -62,7 +63,10 @@
|
|
|
62
63
|
},
|
|
63
64
|
"peerDependencies": {
|
|
64
65
|
"@axonflow/sdk": ">=4.3.0",
|
|
65
|
-
"openclaw": ">=
|
|
66
|
+
"openclaw": ">=2026.4.15"
|
|
67
|
+
},
|
|
68
|
+
"overrides": {
|
|
69
|
+
"openclaw": ">=2026.4.15"
|
|
66
70
|
},
|
|
67
71
|
"devDependencies": {
|
|
68
72
|
"@types/jest": "^29.5.0",
|
|
@@ -71,7 +75,8 @@
|
|
|
71
75
|
"jest": "^29.7.0",
|
|
72
76
|
"ts-jest": "^29.1.0",
|
|
73
77
|
"typescript": "^5.4.0",
|
|
74
|
-
"typescript-eslint": "^8.58.0"
|
|
78
|
+
"typescript-eslint": "^8.58.0",
|
|
79
|
+
"yaml": "^2.8.3"
|
|
75
80
|
},
|
|
76
81
|
"publishConfig": {
|
|
77
82
|
"access": "public",
|
|
@@ -88,10 +93,10 @@
|
|
|
88
93
|
],
|
|
89
94
|
"compat": {
|
|
90
95
|
"pluginApi": ">=2026.3.22",
|
|
91
|
-
"minGatewayVersion": "2026.
|
|
96
|
+
"minGatewayVersion": "2026.4.15"
|
|
92
97
|
},
|
|
93
98
|
"build": {
|
|
94
|
-
"openclawVersion": "2026.
|
|
99
|
+
"openclawVersion": "2026.4.15",
|
|
95
100
|
"pluginSdkVersion": "2026.3.22"
|
|
96
101
|
}
|
|
97
102
|
}
|