@alfe.ai/integrations 0.2.0 → 0.2.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/dist/index.d.ts +20 -0
- package/dist/index.js +86 -5
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -796,6 +796,26 @@ declare class OpenClawApplier implements RuntimeApplier {
|
|
|
796
796
|
* without leaking the value payload.
|
|
797
797
|
*/
|
|
798
798
|
private runConfigCommand;
|
|
799
|
+
/**
|
|
800
|
+
* Read back a single config path and compare it to the value we tried to
|
|
801
|
+
* write. Used by `applyConfig`'s verify-after-write: a `config set` can exit
|
|
802
|
+
* non-zero (a hot-reload races the write, OpenClaw's clobber protection
|
|
803
|
+
* fires) even though the value actually landed, exactly like `applyPlugin`'s
|
|
804
|
+
* install-then-check tolerance.
|
|
805
|
+
*
|
|
806
|
+
* OpenClaw REDACTS sensitive values on `config get`, returning the literal
|
|
807
|
+
* `__OPENCLAW_REDACTED__` instead of the real value. Treat that as a match:
|
|
808
|
+
* the key exists and OpenClaw is hiding it, so a deep-equal against the
|
|
809
|
+
* intended value would otherwise be a false negative and force a re-throw.
|
|
810
|
+
*/
|
|
811
|
+
private configValueMatches;
|
|
812
|
+
/**
|
|
813
|
+
* Run a read-back `check` with the same retry/backoff cadence as the config
|
|
814
|
+
* writes — the settling hot-reload may still be rewriting openclaw.json when
|
|
815
|
+
* we first read back, so a single check can be a false negative. Returns true
|
|
816
|
+
* on the first success, false once all attempts are exhausted.
|
|
817
|
+
*/
|
|
818
|
+
private verifyApplied;
|
|
799
819
|
applyPlugin(spec: string, _installPath?: string, opts?: {
|
|
800
820
|
force?: boolean;
|
|
801
821
|
}): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1702,10 +1702,40 @@ const BUNDLED_BASELINE_ALLOW = ["browser"];
|
|
|
1702
1702
|
*/
|
|
1703
1703
|
const CONFIG_SET_RETRIES$1 = 3;
|
|
1704
1704
|
const CONFIG_SET_RETRY_DELAY_MS$1 = 750;
|
|
1705
|
+
/**
|
|
1706
|
+
* Sentinel OpenClaw returns from `config get` in place of a sensitive value —
|
|
1707
|
+
* the key IS set, OpenClaw is just hiding it. Verify-after-write must treat a
|
|
1708
|
+
* read-back of this as "present/matches" rather than a mismatch (see
|
|
1709
|
+
* `configValueMatches`).
|
|
1710
|
+
*/
|
|
1711
|
+
const OPENCLAW_REDACTED = "__OPENCLAW_REDACTED__";
|
|
1705
1712
|
const delay$1 = (ms) => new Promise((resolve) => {
|
|
1706
1713
|
setTimeout(resolve, ms);
|
|
1707
1714
|
});
|
|
1708
1715
|
/**
|
|
1716
|
+
* Structural equality for config read-back comparison. Primitives compare by
|
|
1717
|
+
* `Object.is`; arrays are order-SENSITIVE (config arrays are positional);
|
|
1718
|
+
* plain objects are order-INSENSITIVE (key order in JSON is not meaningful).
|
|
1719
|
+
* Used only to confirm a value landed after a `config set` exited non-zero.
|
|
1720
|
+
*/
|
|
1721
|
+
function deepEqual(a, b) {
|
|
1722
|
+
if (Object.is(a, b)) return true;
|
|
1723
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
1724
|
+
const aIsArr = Array.isArray(a);
|
|
1725
|
+
const bIsArr = Array.isArray(b);
|
|
1726
|
+
if (aIsArr !== bIsArr) return false;
|
|
1727
|
+
if (aIsArr && bIsArr) {
|
|
1728
|
+
if (a.length !== b.length) return false;
|
|
1729
|
+
return a.every((v, i) => deepEqual(v, b[i]));
|
|
1730
|
+
}
|
|
1731
|
+
const ao = a;
|
|
1732
|
+
const bo = b;
|
|
1733
|
+
const aKeys = Object.keys(ao);
|
|
1734
|
+
const bKeys = Object.keys(bo);
|
|
1735
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
1736
|
+
return aKeys.every((k) => Object.prototype.hasOwnProperty.call(bo, k) && deepEqual(ao[k], bo[k]));
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1709
1739
|
* Describe a `config set` target WITHOUT leaking values. The value argument is
|
|
1710
1740
|
* the JSON payload (model config, the gateway loopback token via the alfe hook,
|
|
1711
1741
|
* etc.) and must never reach the integration's `errorMessage`, which projects
|
|
@@ -1793,6 +1823,45 @@ var OpenClawApplier = class {
|
|
|
1793
1823
|
this.configSetQueue = result.catch(() => void 0);
|
|
1794
1824
|
return result;
|
|
1795
1825
|
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Read back a single config path and compare it to the value we tried to
|
|
1828
|
+
* write. Used by `applyConfig`'s verify-after-write: a `config set` can exit
|
|
1829
|
+
* non-zero (a hot-reload races the write, OpenClaw's clobber protection
|
|
1830
|
+
* fires) even though the value actually landed, exactly like `applyPlugin`'s
|
|
1831
|
+
* install-then-check tolerance.
|
|
1832
|
+
*
|
|
1833
|
+
* OpenClaw REDACTS sensitive values on `config get`, returning the literal
|
|
1834
|
+
* `__OPENCLAW_REDACTED__` instead of the real value. Treat that as a match:
|
|
1835
|
+
* the key exists and OpenClaw is hiding it, so a deep-equal against the
|
|
1836
|
+
* intended value would otherwise be a false negative and force a re-throw.
|
|
1837
|
+
*/
|
|
1838
|
+
async configValueMatches(path, expected) {
|
|
1839
|
+
try {
|
|
1840
|
+
const { stdout } = await execFileAsync$1("openclaw", [
|
|
1841
|
+
"config",
|
|
1842
|
+
"get",
|
|
1843
|
+
path
|
|
1844
|
+
], { timeout: 1e4 });
|
|
1845
|
+
const actual = JSON.parse(stdout.trim());
|
|
1846
|
+
if (actual === OPENCLAW_REDACTED) return true;
|
|
1847
|
+
return deepEqual(actual, expected);
|
|
1848
|
+
} catch {
|
|
1849
|
+
return false;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
/**
|
|
1853
|
+
* Run a read-back `check` with the same retry/backoff cadence as the config
|
|
1854
|
+
* writes — the settling hot-reload may still be rewriting openclaw.json when
|
|
1855
|
+
* we first read back, so a single check can be a false negative. Returns true
|
|
1856
|
+
* on the first success, false once all attempts are exhausted.
|
|
1857
|
+
*/
|
|
1858
|
+
async verifyApplied(check) {
|
|
1859
|
+
for (let attempt = 0; attempt <= this.configSetRetries; attempt++) {
|
|
1860
|
+
if (await check()) return true;
|
|
1861
|
+
if (attempt < this.configSetRetries && this.configSetRetryDelayMs > 0) await delay$1(this.configSetRetryDelayMs * 2 ** attempt);
|
|
1862
|
+
}
|
|
1863
|
+
return false;
|
|
1864
|
+
}
|
|
1796
1865
|
async applyPlugin(spec, _installPath, opts) {
|
|
1797
1866
|
const pkg = stripPluginVersion(spec);
|
|
1798
1867
|
await this.ensurePluginsAllow(pkg);
|
|
@@ -2023,6 +2092,13 @@ var OpenClawApplier = class {
|
|
|
2023
2092
|
try {
|
|
2024
2093
|
await this.runConfigSet([parentPath, JSON.stringify(merged)]);
|
|
2025
2094
|
} catch (err) {
|
|
2095
|
+
if (await this.verifyApplied(async () => {
|
|
2096
|
+
const after = await readParentObject(parentPath);
|
|
2097
|
+
return [...dottedKvs.entries()].every(([k, v]) => deepEqual(after[k], v));
|
|
2098
|
+
})) {
|
|
2099
|
+
log$3.warn({ parentPath }, "openclaw config set exited non-zero but config landed — continuing");
|
|
2100
|
+
continue;
|
|
2101
|
+
}
|
|
2026
2102
|
log$3.error({
|
|
2027
2103
|
err: err instanceof Error ? err.message : String(err),
|
|
2028
2104
|
parentPath
|
|
@@ -2033,11 +2109,16 @@ var OpenClawApplier = class {
|
|
|
2033
2109
|
if (leaves.length > 0) try {
|
|
2034
2110
|
await this.runConfigSet(["--batch-json", JSON.stringify(leaves)]);
|
|
2035
2111
|
} catch (err) {
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2112
|
+
if (await this.verifyApplied(async () => {
|
|
2113
|
+
return (await Promise.all(leaves.map((l) => this.configValueMatches(l.path, l.value)))).every(Boolean);
|
|
2114
|
+
})) log$3.warn({ count: leaves.length }, "openclaw config set --batch-json exited non-zero but config landed — continuing");
|
|
2115
|
+
else {
|
|
2116
|
+
log$3.error({
|
|
2117
|
+
err: err instanceof Error ? err.message : String(err),
|
|
2118
|
+
batch: leaves
|
|
2119
|
+
}, "Failed to set config via openclaw config set --batch-json");
|
|
2120
|
+
throw err;
|
|
2121
|
+
}
|
|
2041
2122
|
}
|
|
2042
2123
|
}
|
|
2043
2124
|
/**
|
package/package.json
CHANGED