@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
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Community-SaaS bootstrap context — environment + filesystem operations.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the split applied to the heartbeat path: env access and fs
|
|
5
|
+
* reads/writes live here, away from the network-sending side
|
|
6
|
+
* (community-saas-bootstrap.ts). Static-analysis heuristics that flag
|
|
7
|
+
* env-or-fs-read co-located with outbound HTTP therefore do not trip on
|
|
8
|
+
* the compiled bootstrap module.
|
|
9
|
+
*
|
|
10
|
+
* Pure-data module: callers receive plain values and pass them into the
|
|
11
|
+
* orchestration layer. No outbound HTTP lives here.
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from "fs";
|
|
14
|
+
import * as os from "os";
|
|
15
|
+
import * as path from "path";
|
|
16
|
+
const DISCLOSURE_STAMP_NAME = "openclaw-plugin-community-saas-disclosure-shown";
|
|
17
|
+
export function resolveHarnessInputs() {
|
|
18
|
+
const harnessOn = process.env["AXONFLOW_HARNESS"] === "1";
|
|
19
|
+
const harnessRegisterUrl = harnessOn ? (process.env["AXONFLOW_HARNESS_REGISTER_URL"] ?? "") : "";
|
|
20
|
+
const harnessAgentEndpoint = harnessOn ? (process.env["AXONFLOW_HARNESS_AGENT_ENDPOINT"] ?? "") : "";
|
|
21
|
+
return { harnessOn, harnessRegisterUrl, harnessAgentEndpoint };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Operator opt-out for Community-SaaS auto-bootstrap. Honours
|
|
25
|
+
* AXONFLOW_COMMUNITY_SAAS = "0" | "false" | "off" | "no"
|
|
26
|
+
* (case-insensitive). Any other value (including unset) leaves the default
|
|
27
|
+
* auto-bootstrap behaviour unchanged.
|
|
28
|
+
*
|
|
29
|
+
* This is the only programmatic way an operator can disable the implicit
|
|
30
|
+
* try.getaxonflow.com registration without supplying a self-hosted
|
|
31
|
+
* endpoint. Documented in README and surfaced in the first-load disclosure
|
|
32
|
+
* banner so the consent surface is real.
|
|
33
|
+
*/
|
|
34
|
+
export function isCommunitySaasOptedOut() {
|
|
35
|
+
const raw = process.env["AXONFLOW_COMMUNITY_SAAS"];
|
|
36
|
+
if (typeof raw !== "string")
|
|
37
|
+
return false;
|
|
38
|
+
const normalized = raw.trim().toLowerCase();
|
|
39
|
+
return normalized === "0" || normalized === "false" || normalized === "off" || normalized === "no";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Ensure a directory exists with mode 0o700 (owner-only on POSIX). Returns
|
|
43
|
+
* true on success or false on any failure so callers can degrade safely.
|
|
44
|
+
*/
|
|
45
|
+
export function ensureSecureDir(dir) {
|
|
46
|
+
if (!dir)
|
|
47
|
+
return false;
|
|
48
|
+
try {
|
|
49
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
50
|
+
if (process.platform !== "win32") {
|
|
51
|
+
try {
|
|
52
|
+
fs.chmodSync(dir, 0o700);
|
|
53
|
+
}
|
|
54
|
+
catch { /* best effort */ }
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Read a Community-SaaS registration file if it is fresh enough to use,
|
|
64
|
+
* has well-formed contents, and (on POSIX) lives at mode 0o600. Returns
|
|
65
|
+
* null when the file is missing, malformed, expired, or unsafe.
|
|
66
|
+
*
|
|
67
|
+
* `refreshWindowMs` lets the caller decide how aggressively to refresh —
|
|
68
|
+
* passing the same window ensures cached + fresh paths agree on lifetime.
|
|
69
|
+
*/
|
|
70
|
+
export function readRegistrationIfFreshAndSafe(file, now, refreshWindowMs) {
|
|
71
|
+
let stat;
|
|
72
|
+
try {
|
|
73
|
+
stat = fs.statSync(file);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (process.platform !== "win32") {
|
|
79
|
+
const mode = stat.mode & 0o777;
|
|
80
|
+
if (mode !== 0o600) {
|
|
81
|
+
try {
|
|
82
|
+
process.stderr.write(`[AxonFlow] ${file} has unsafe permissions (${mode.toString(8).padStart(3, "0")}); refusing to use. ` +
|
|
83
|
+
`Re-register: rm ${JSON.stringify(file)} and reload.\n`);
|
|
84
|
+
}
|
|
85
|
+
catch { /* stderr unavailable in some hosts */ }
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
let parsed;
|
|
90
|
+
try {
|
|
91
|
+
const raw = fs.readFileSync(file, "utf8");
|
|
92
|
+
parsed = JSON.parse(raw);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
if (typeof parsed.tenant_id !== "string" || parsed.tenant_id.length === 0 ||
|
|
98
|
+
typeof parsed.secret !== "string" || parsed.secret.length === 0 ||
|
|
99
|
+
typeof parsed.expires_at !== "string") {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const expiresMs = Date.parse(parsed.expires_at);
|
|
103
|
+
if (!Number.isFinite(expiresMs)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const remaining = expiresMs - now().getTime();
|
|
107
|
+
if (remaining < refreshWindowMs) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return parsed;
|
|
111
|
+
}
|
|
112
|
+
export function isWithinBackoff(backoffFile, now) {
|
|
113
|
+
if (!backoffFile)
|
|
114
|
+
return false;
|
|
115
|
+
try {
|
|
116
|
+
const raw = fs.readFileSync(backoffFile, "utf8").trim();
|
|
117
|
+
const until = Number(raw);
|
|
118
|
+
if (!Number.isFinite(until) || until <= 0)
|
|
119
|
+
return false;
|
|
120
|
+
return until > Math.floor(now().getTime() / 1000);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Atomic file write (tmp + rename) with an explicit POSIX mode. Used for
|
|
128
|
+
* the registration file (0o600) and the rate-limit backoff stamp (0o600).
|
|
129
|
+
*/
|
|
130
|
+
export function writeFileAtomicallyWithMode(file, content, mode) {
|
|
131
|
+
const dir = path.dirname(file);
|
|
132
|
+
const tmp = path.join(dir, `${path.basename(file)}.tmp.${process.pid}`);
|
|
133
|
+
fs.writeFileSync(tmp, content, { mode });
|
|
134
|
+
try {
|
|
135
|
+
fs.chmodSync(tmp, mode);
|
|
136
|
+
}
|
|
137
|
+
catch { /* best effort */ }
|
|
138
|
+
fs.renameSync(tmp, file);
|
|
139
|
+
}
|
|
140
|
+
export function unlinkIfExists(file) {
|
|
141
|
+
if (!file)
|
|
142
|
+
return;
|
|
143
|
+
try {
|
|
144
|
+
fs.unlinkSync(file);
|
|
145
|
+
}
|
|
146
|
+
catch { /* fine — already gone */ }
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the registration label sent in the POST body. Pure stdlib — no env
|
|
150
|
+
* reads, no fs reads — kept here so the bootstrap module stays free of any
|
|
151
|
+
* `os.*` calls that might confuse future scanner heuristics.
|
|
152
|
+
*/
|
|
153
|
+
export function buildRegistrationLabel(pluginVersion) {
|
|
154
|
+
const version = pluginVersion ?? "unknown";
|
|
155
|
+
const platform = `${os.type()}-${os.arch()}`;
|
|
156
|
+
const label = `openclaw-plugin@${version} / ${platform}`;
|
|
157
|
+
return label.length > 255 ? label.slice(0, 255) : label;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* First-load disclosure stamp helpers. The bootstrap path emits a one-time
|
|
161
|
+
* warning to the plugin logger explaining that auto-Community-SaaS
|
|
162
|
+
* registration is about to happen and how to opt out. The stamp keeps the
|
|
163
|
+
* warning from re-firing on every plugin reload.
|
|
164
|
+
*
|
|
165
|
+
* Stamp file lives next to the registration file so it shares the same
|
|
166
|
+
* config-dir lifecycle (rm of try-registration.json without a re-warn is
|
|
167
|
+
* intentional; the user already knows we register).
|
|
168
|
+
*/
|
|
169
|
+
export function disclosureStampPath(configDir) {
|
|
170
|
+
if (!configDir)
|
|
171
|
+
return "";
|
|
172
|
+
return path.join(configDir, DISCLOSURE_STAMP_NAME);
|
|
173
|
+
}
|
|
174
|
+
export function hasShownDisclosure(stampFile) {
|
|
175
|
+
if (!stampFile)
|
|
176
|
+
return false;
|
|
177
|
+
try {
|
|
178
|
+
fs.statSync(stampFile);
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export function markDisclosureShown(stampFile) {
|
|
186
|
+
if (!stampFile)
|
|
187
|
+
return;
|
|
188
|
+
try {
|
|
189
|
+
writeFileAtomicallyWithMode(stampFile, new Date().toISOString(), 0o600);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Best effort. If we can't stamp, we'll re-warn on the next load.
|
|
193
|
+
// That's louder than ideal but never silent or wrong.
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=community-saas-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"community-saas-context.js","sourceRoot":"","sources":["../src/community-saas-context.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -64,8 +64,33 @@ export interface AxonFlowPluginConfig {
|
|
|
64
64
|
* Defaults to 8000ms.
|
|
65
65
|
*/
|
|
66
66
|
requestTimeoutMs?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Resolved deployment mode (set by `resolveConfig`):
|
|
69
|
+
* - "community-saas": user provided no explicit endpoint/clientId/clientSecret;
|
|
70
|
+
* plugin will register against try.getaxonflow.com on first run.
|
|
71
|
+
* - "self-hosted": user provided at least one of endpoint/clientId/clientSecret;
|
|
72
|
+
* plugin uses those values verbatim (no Community-SaaS bootstrap).
|
|
73
|
+
*
|
|
74
|
+
* Surfaced on the config so callers can emit the mode-clarity canary
|
|
75
|
+
* "[AxonFlow] Connected to AxonFlow at <URL> (mode=<X>)" and so the
|
|
76
|
+
* Gate 4 mode-clarity test can assert it.
|
|
77
|
+
*/
|
|
78
|
+
mode: "community-saas" | "self-hosted";
|
|
67
79
|
}
|
|
68
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* Validate plugin config and return defaults.
|
|
82
|
+
*
|
|
83
|
+
* Resolution order (ADR-048):
|
|
84
|
+
* 1. If the user provided ANY of endpoint, clientId, clientSecret → mode is
|
|
85
|
+
* "self-hosted". Defaults are filled in: endpoint defaults to localhost,
|
|
86
|
+
* clientId defaults to "community", clientSecret stays empty (community
|
|
87
|
+
* mode). The user's explicit values are honoured untouched.
|
|
88
|
+
* 2. If the user provided NONE → mode is "community-saas". Endpoint
|
|
89
|
+
* defaults to https://try.getaxonflow.com. clientId/clientSecret stay
|
|
90
|
+
* EMPTY here — the caller (registerAxonFlowGovernance) is expected to
|
|
91
|
+
* bootstrap the registration via community-saas-bootstrap.ts and
|
|
92
|
+
* override clientId/clientSecret on the resulting client.
|
|
93
|
+
*/
|
|
69
94
|
export declare function resolveConfig(raw: Record<string, unknown> | undefined): AxonFlowPluginConfig;
|
|
70
95
|
/** Check if a tool should be governed based on config. */
|
|
71
96
|
export declare function shouldGovernTool(toolName: string, config: AxonFlowPluginConfig): boolean;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,oBAAoB;IACnC,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IAEjB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IAEjB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAE5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,oBAAoB;IACnC,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IAEjB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IAEjB,gFAAgF;IAChF,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAE5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;OAUG;IACH,IAAI,EAAE,gBAAgB,GAAG,aAAa,CAAC;CACxC;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GACvC,oBAAoB,CAyEtB;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAWT"}
|
package/dist/config.js
CHANGED
|
@@ -4,50 +4,80 @@
|
|
|
4
4
|
* All configuration is read from the OpenClaw plugin config system
|
|
5
5
|
* (openclaw.plugin.json or runtime config).
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
const COMMUNITY_SAAS_DEFAULT_ENDPOINT = "https://try.getaxonflow.com";
|
|
8
|
+
/**
|
|
9
|
+
* Validate plugin config and return defaults.
|
|
10
|
+
*
|
|
11
|
+
* Resolution order (ADR-048):
|
|
12
|
+
* 1. If the user provided ANY of endpoint, clientId, clientSecret → mode is
|
|
13
|
+
* "self-hosted". Defaults are filled in: endpoint defaults to localhost,
|
|
14
|
+
* clientId defaults to "community", clientSecret stays empty (community
|
|
15
|
+
* mode). The user's explicit values are honoured untouched.
|
|
16
|
+
* 2. If the user provided NONE → mode is "community-saas". Endpoint
|
|
17
|
+
* defaults to https://try.getaxonflow.com. clientId/clientSecret stay
|
|
18
|
+
* EMPTY here — the caller (registerAxonFlowGovernance) is expected to
|
|
19
|
+
* bootstrap the registration via community-saas-bootstrap.ts and
|
|
20
|
+
* override clientId/clientSecret on the resulting client.
|
|
21
|
+
*/
|
|
8
22
|
export function resolveConfig(raw) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
// Defaults match SDK behavior: community mode works out of the box.
|
|
17
|
-
// Override with your evaluation/enterprise license credentials.
|
|
18
|
-
const rawClientId = typeof raw["clientId"] === "string" ? raw["clientId"] : "";
|
|
19
|
-
const rawClientSecret = typeof raw["clientSecret"] === "string" ? raw["clientSecret"] : "";
|
|
20
|
-
// Reject clientSecret without clientId — licensed mode must specify the tenant
|
|
23
|
+
const safe = raw ?? {};
|
|
24
|
+
const rawEndpoint = typeof safe["endpoint"] === "string" ? safe["endpoint"].trim() : "";
|
|
25
|
+
const rawClientId = typeof safe["clientId"] === "string" ? safe["clientId"].trim() : "";
|
|
26
|
+
const rawClientSecret = typeof safe["clientSecret"] === "string" ? safe["clientSecret"].trim() : "";
|
|
27
|
+
// Reject clientSecret without clientId regardless of mode — licensed
|
|
28
|
+
// setups must specify the tenant identity.
|
|
21
29
|
if (!rawClientId && rawClientSecret) {
|
|
22
30
|
throw new Error("AxonFlow plugin: 'clientId' is required when 'clientSecret' is set. " +
|
|
23
31
|
"Set clientId to your tenant identity (e.g., your deployment's AXONFLOW_CLIENT_ID).");
|
|
24
32
|
}
|
|
25
|
-
const
|
|
26
|
-
|
|
33
|
+
const userProvidedAnything = rawEndpoint !== "" || rawClientId !== "" || rawClientSecret !== "";
|
|
34
|
+
let endpoint;
|
|
35
|
+
let clientId;
|
|
36
|
+
let clientSecret;
|
|
37
|
+
let mode;
|
|
38
|
+
if (userProvidedAnything) {
|
|
39
|
+
mode = "self-hosted";
|
|
40
|
+
// Endpoint default for self-hosted users who set credentials but not
|
|
41
|
+
// endpoint: assume the canonical local-agent URL. Matches the bash
|
|
42
|
+
// plugins' resolution rule.
|
|
43
|
+
endpoint = rawEndpoint || "http://localhost:8080";
|
|
44
|
+
clientId = rawClientId || "community";
|
|
45
|
+
clientSecret = rawClientSecret;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
mode = "community-saas";
|
|
49
|
+
endpoint = COMMUNITY_SAAS_DEFAULT_ENDPOINT;
|
|
50
|
+
// Bootstrap will fill these in. We deliberately leave them empty here
|
|
51
|
+
// so a misconfigured caller that skips the bootstrap step gets a clear
|
|
52
|
+
// 401 from the agent rather than a half-credentialled request.
|
|
53
|
+
clientId = "";
|
|
54
|
+
clientSecret = "";
|
|
55
|
+
}
|
|
27
56
|
return {
|
|
28
57
|
endpoint,
|
|
29
58
|
clientId,
|
|
30
59
|
clientSecret,
|
|
31
|
-
|
|
32
|
-
|
|
60
|
+
mode,
|
|
61
|
+
userEmail: typeof safe["userEmail"] === "string" && safe["userEmail"].trim()
|
|
62
|
+
? safe["userEmail"].trim()
|
|
33
63
|
: undefined,
|
|
34
|
-
highRiskTools: Array.isArray(
|
|
35
|
-
?
|
|
64
|
+
highRiskTools: Array.isArray(safe["highRiskTools"])
|
|
65
|
+
? safe["highRiskTools"]
|
|
36
66
|
: [],
|
|
37
|
-
governedTools: Array.isArray(
|
|
38
|
-
?
|
|
67
|
+
governedTools: Array.isArray(safe["governedTools"])
|
|
68
|
+
? safe["governedTools"]
|
|
39
69
|
: [],
|
|
40
|
-
excludedTools: Array.isArray(
|
|
41
|
-
?
|
|
70
|
+
excludedTools: Array.isArray(safe["excludedTools"])
|
|
71
|
+
? safe["excludedTools"]
|
|
42
72
|
: [],
|
|
43
|
-
defaultOperation: typeof
|
|
44
|
-
?
|
|
73
|
+
defaultOperation: typeof safe["defaultOperation"] === "string"
|
|
74
|
+
? safe["defaultOperation"]
|
|
45
75
|
: "execute",
|
|
46
|
-
onError:
|
|
47
|
-
requestTimeoutMs: typeof
|
|
48
|
-
Number.isFinite(
|
|
49
|
-
|
|
50
|
-
?
|
|
76
|
+
onError: safe["onError"] === "allow" ? "allow" : "block",
|
|
77
|
+
requestTimeoutMs: typeof safe["requestTimeoutMs"] === "number" &&
|
|
78
|
+
Number.isFinite(safe["requestTimeoutMs"]) &&
|
|
79
|
+
safe["requestTimeoutMs"] > 0
|
|
80
|
+
? safe["requestTimeoutMs"]
|
|
51
81
|
: 8000,
|
|
52
82
|
};
|
|
53
83
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/governance.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Evaluates tool arguments against AxonFlow policies before execution.
|
|
5
5
|
* Can block the call, require human approval, or allow through.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { MCPCheckInputResponse } from "./axonflow-client.js";
|
|
8
|
+
import type { ClientRef } from "./client-ref.js";
|
|
8
9
|
import type { AxonFlowPluginConfig } from "./config.js";
|
|
9
10
|
/** Result type matching OpenClaw's PluginHookBeforeToolCallResult. */
|
|
10
11
|
export interface BeforeToolCallResult {
|
|
@@ -63,7 +64,7 @@ export declare function isAxonFlowAuthError(err: unknown): boolean;
|
|
|
63
64
|
* 4. If tool is in highRiskTools AND allowed: return { requireApproval }
|
|
64
65
|
* 5. Otherwise: allow through
|
|
65
66
|
*/
|
|
66
|
-
export declare function createBeforeToolCallHandler(
|
|
67
|
+
export declare function createBeforeToolCallHandler(clientRef: ClientRef, config: AxonFlowPluginConfig): (event: {
|
|
67
68
|
toolName: string;
|
|
68
69
|
params: Record<string, unknown>;
|
|
69
70
|
runId?: string;
|
package/dist/governance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governance.d.ts","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"governance.d.ts","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAUxD,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;QAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;KACpC,CAAC;CACH;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAgBxE;AAoCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAazD;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,oBAAoB,IAEd,OAAO;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,KAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAoF9C"}
|
package/dist/governance.js
CHANGED
|
@@ -113,7 +113,7 @@ export function isAxonFlowAuthError(err) {
|
|
|
113
113
|
* 4. If tool is in highRiskTools AND allowed: return { requireApproval }
|
|
114
114
|
* 5. Otherwise: allow through
|
|
115
115
|
*/
|
|
116
|
-
export function createBeforeToolCallHandler(
|
|
116
|
+
export function createBeforeToolCallHandler(clientRef, config) {
|
|
117
117
|
return async (event) => {
|
|
118
118
|
if (!shouldGovernTool(event.toolName, config)) {
|
|
119
119
|
return undefined;
|
|
@@ -123,7 +123,7 @@ export function createBeforeToolCallHandler(client, config) {
|
|
|
123
123
|
const statement = JSON.stringify(event.params);
|
|
124
124
|
let check;
|
|
125
125
|
try {
|
|
126
|
-
check = await
|
|
126
|
+
check = await clientRef.current.mcpCheckInput(connectorType, statement, config.defaultOperation ?? "execute");
|
|
127
127
|
}
|
|
128
128
|
catch (err) {
|
|
129
129
|
recordGovernanceError();
|
package/dist/governance.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"governance.js","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"governance.js","sourceRoot":"","sources":["../src/governance.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* for async hook support.
|
|
32
32
|
*/
|
|
33
33
|
/** Plugin version — update before each release. */
|
|
34
|
-
export declare const VERSION = "
|
|
34
|
+
export declare const VERSION = "2.0.1";
|
|
35
35
|
export { AxonFlowClient } from "./axonflow-client.js";
|
|
36
36
|
export type { AxonFlowPluginConfig } from "./config.js";
|
|
37
37
|
export { resolveConfig, shouldGovernTool } from "./config.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAcH,mDAAmD;AACnD,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE;IAC9C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACpG,EAAE,EAAE,CACF,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAChC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KACzB,IAAI,CAAC;CACX,GAAG,IAAI,CA6IP;AAED;;;;;;GAMG;;;;;;;AACH,wBAKE"}
|
package/dist/index.js
CHANGED
|
@@ -37,9 +37,11 @@ import { createAfterToolCallHandler } from "./audit.js";
|
|
|
37
37
|
import { createMessageSendingHandler } from "./message-guard.js";
|
|
38
38
|
import { createLlmInputHandler, createLlmOutputHandler } from "./llm-audit.js";
|
|
39
39
|
import { sendTelemetryPing } from "./telemetry.js";
|
|
40
|
+
import { bootstrapCommunitySaas } from "./community-saas-bootstrap.js";
|
|
40
41
|
import { resetMetrics } from "./metrics.js";
|
|
42
|
+
import { runPluginVersionCheck } from "./plugin-version-check.js";
|
|
41
43
|
/** Plugin version — update before each release. */
|
|
42
|
-
export const VERSION = "
|
|
44
|
+
export const VERSION = "2.0.1";
|
|
43
45
|
// Re-export for external consumers
|
|
44
46
|
export { AxonFlowClient } from "./axonflow-client.js";
|
|
45
47
|
export { resolveConfig, shouldGovernTool } from "./config.js";
|
|
@@ -54,13 +56,87 @@ export { getMetrics } from "./metrics.js";
|
|
|
54
56
|
*/
|
|
55
57
|
export function registerAxonFlowGovernance(api) {
|
|
56
58
|
const config = resolveConfig(api.pluginConfig);
|
|
57
|
-
const client = new AxonFlowClient(config);
|
|
58
59
|
// Reset metrics on each registration (handles hot-reload)
|
|
59
60
|
resetMetrics();
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
// Mode-clarity canary — emitted on every plugin init so users always know
|
|
62
|
+
// which AxonFlow they're connected to. The Gate 4 mode-clarity test
|
|
63
|
+
// (tests/mode-clarity.test.ts) parses this exact line and asserts
|
|
64
|
+
// URL + mode match the resolved config.
|
|
65
|
+
api.logger.info(`[AxonFlow] Connected to AxonFlow at ${config.endpoint} (mode=${config.mode})`);
|
|
66
|
+
// In community-saas mode, register asynchronously against try.getaxonflow.com
|
|
67
|
+
// and override the client credentials with the bootstrapped values once
|
|
68
|
+
// they arrive. The startup health check + the first hook fire happen
|
|
69
|
+
// immediately; if the bootstrap is still pending when a hook fires, the
|
|
70
|
+
// existing AxonFlowClient handles the (transient) 401 and retries with
|
|
71
|
+
// the new credentials on the next call once they're loaded.
|
|
72
|
+
// Mutable holder so the bootstrap reassignment below is visible to every
|
|
73
|
+
// hook factory we register. Hook factories close over `clientRef` and read
|
|
74
|
+
// `clientRef.current.<method>(...)` so swapping in a freshly-credentialled
|
|
75
|
+
// client after the async bootstrap completes propagates immediately.
|
|
76
|
+
// Without this indirection the bootstrap would silently no-op for hooks
|
|
77
|
+
// (they'd keep using the empty-credential client they were registered with).
|
|
78
|
+
const clientRef = { current: new AxonFlowClient(config) };
|
|
79
|
+
if (config.mode === "community-saas") {
|
|
80
|
+
void bootstrapCommunitySaas({
|
|
81
|
+
endpoint: config.endpoint,
|
|
82
|
+
pluginVersion: VERSION,
|
|
83
|
+
// Surface the first-load consent disclosure through the plugin
|
|
84
|
+
// logger so it shows up alongside other plugin warnings rather than
|
|
85
|
+
// only on stderr. The bootstrap module fires the banner at most
|
|
86
|
+
// once per machine (stamp file in the config dir).
|
|
87
|
+
disclosureLogger: (msg) => {
|
|
88
|
+
if (api.logger.warn) {
|
|
89
|
+
api.logger.warn(msg);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
api.logger.error(msg);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
}).then((result) => {
|
|
96
|
+
if (!result || result.source === "failed" || result.source === "rate-limited") {
|
|
97
|
+
const detail = result?.source === "rate-limited"
|
|
98
|
+
? "rate-limited (will retry)"
|
|
99
|
+
: "failed (network error or non-2xx response)";
|
|
100
|
+
const msg = `AxonFlow Community SaaS registration ${detail}. Tool calls will fail-${config.onError === "allow" ? "open (allow through)" : "closed (block)"} until registration succeeds.`;
|
|
101
|
+
if (api.logger.warn) {
|
|
102
|
+
api.logger.warn(msg);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
api.logger.error(msg);
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (result.source === "opted-out") {
|
|
110
|
+
// Operator set AXONFLOW_COMMUNITY_SAAS=0. The plugin loaded but
|
|
111
|
+
// is not registered with any AxonFlow instance. Surface this so
|
|
112
|
+
// the operator sees why governance calls might fail-open or
|
|
113
|
+
// fail-closed depending on onError config.
|
|
114
|
+
const msg = "AxonFlow Community SaaS auto-bootstrap skipped (AXONFLOW_COMMUNITY_SAAS=0). " +
|
|
115
|
+
"Set pluginConfig.endpoint to a self-hosted AxonFlow instance, or unset the " +
|
|
116
|
+
"opt-out env var to register with try.getaxonflow.com.";
|
|
117
|
+
if (api.logger.warn) {
|
|
118
|
+
api.logger.warn(msg);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
api.logger.error(msg);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const enriched = {
|
|
126
|
+
...config,
|
|
127
|
+
endpoint: result.endpoint,
|
|
128
|
+
clientId: result.clientId,
|
|
129
|
+
clientSecret: result.clientSecret,
|
|
130
|
+
};
|
|
131
|
+
clientRef.current = new AxonFlowClient(enriched);
|
|
132
|
+
api.logger.info(`[AxonFlow] Community SaaS registration ${result.source === "fresh-registration" ? "complete" : "loaded from cache"} (tenant=${result.clientId.slice(0, 16)}...)`);
|
|
133
|
+
}).catch(() => {
|
|
134
|
+
// Silent — bootstrap should never block plugin registration. The
|
|
135
|
+
// governance handlers will fail-open or fail-closed per onError config.
|
|
136
|
+
});
|
|
137
|
+
}
|
|
62
138
|
// Startup health check (fire-and-forget, non-blocking)
|
|
63
|
-
void
|
|
139
|
+
void clientRef.current.healthCheck().then((healthy) => {
|
|
64
140
|
if (healthy) {
|
|
65
141
|
api.logger.info(`AxonFlow connected: ${config.endpoint}`);
|
|
66
142
|
}
|
|
@@ -76,28 +152,37 @@ export function registerAxonFlowGovernance(api) {
|
|
|
76
152
|
}).catch(() => {
|
|
77
153
|
// Silent — health check should never prevent plugin registration
|
|
78
154
|
});
|
|
155
|
+
// Plugin/platform version compatibility check (fire-and-forget,
|
|
156
|
+
// platform 7.5.0+). Mirrors what the SDKs already do at startup —
|
|
157
|
+
// emits a one-time upgrade warning when the plugin's own version is
|
|
158
|
+
// below the floor the platform expects, stays silent otherwise.
|
|
159
|
+
// Failure modes (network error, older platform, malformed response)
|
|
160
|
+
// are swallowed by runPluginVersionCheck — never blocks startup.
|
|
161
|
+
void runPluginVersionCheck(clientRef.current, VERSION, api.logger);
|
|
79
162
|
// Hook 1: Input governance (before tool execution)
|
|
80
|
-
const beforeToolCall = createBeforeToolCallHandler(
|
|
163
|
+
const beforeToolCall = createBeforeToolCallHandler(clientRef, config);
|
|
81
164
|
api.on("before_tool_call", beforeToolCall, { priority: 10 });
|
|
82
165
|
// Hook 2: Audit logging (after tool execution)
|
|
83
|
-
const afterToolCall = createAfterToolCallHandler(
|
|
166
|
+
const afterToolCall = createAfterToolCallHandler(clientRef, config);
|
|
84
167
|
api.on("after_tool_call", afterToolCall, { priority: 90 });
|
|
85
168
|
// Hook 3: Outbound message governance (before message reaches user)
|
|
86
|
-
const messageSending = createMessageSendingHandler(
|
|
169
|
+
const messageSending = createMessageSendingHandler(clientRef, config);
|
|
87
170
|
api.on("message_sending", messageSending, { priority: 10 });
|
|
88
171
|
// Hook 4-5: LLM call audit (observe-only, cannot block/modify)
|
|
89
172
|
const llmCallState = new Map();
|
|
90
|
-
const llmInput = createLlmInputHandler(
|
|
173
|
+
const llmInput = createLlmInputHandler(clientRef, config, llmCallState);
|
|
91
174
|
api.on("llm_input", llmInput, { priority: 90 });
|
|
92
|
-
const llmOutput = createLlmOutputHandler(
|
|
175
|
+
const llmOutput = createLlmOutputHandler(clientRef, config, llmCallState);
|
|
93
176
|
api.on("llm_output", llmOutput, { priority: 90 });
|
|
94
|
-
// Telemetry (fire-and-forget
|
|
95
|
-
|
|
177
|
+
// Telemetry — 7-day heartbeat (fire-and-forget; opt out with
|
|
178
|
+
// AXONFLOW_TELEMETRY=off). The promise is intentionally not awaited.
|
|
179
|
+
void sendTelemetryPing({
|
|
96
180
|
endpoint: config.endpoint,
|
|
97
181
|
pluginVersion: VERSION,
|
|
98
182
|
hookCount: 5,
|
|
99
183
|
highRiskToolCount: (config.highRiskTools ?? []).length,
|
|
100
184
|
onError: config.onError ?? "block",
|
|
185
|
+
mode: config.mode,
|
|
101
186
|
});
|
|
102
187
|
}
|
|
103
188
|
/**
|
|
@@ -113,4 +198,5 @@ export default {
|
|
|
113
198
|
description: "Policy enforcement for tool inputs, PII scanning on outbound messages, and audit trails for OpenClaw",
|
|
114
199
|
register: registerAxonFlowGovernance,
|
|
115
200
|
};
|
|
201
|
+
// CI re-trigger: 1777491400
|
|
116
202
|
//# sourceMappingURL=index.js.map
|