@openclaw/diffs 2026.8.33 → 2026.8.35

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.
Files changed (2) hide show
  1. package/dist/index.js +173 -2
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -5,7 +5,6 @@ import { buildPluginConfigSchema } from "openclaw/plugin-sdk/plugin-entry";
5
5
  import { mapPluginConfigIssues } from "openclaw/plugin-sdk/extension-shared";
6
6
  import { z } from "zod";
7
7
  import { resolveGatewayPublicOrigin } from "openclaw/plugin-sdk/config-contracts";
8
- import { resolveGatewayPort } from "openclaw/plugin-sdk/gateway-config-runtime";
9
8
  import fs from "node:fs";
10
9
  import path from "node:path";
11
10
  import { resolveLivePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
@@ -25,6 +24,32 @@ import { Type } from "typebox";
25
24
  import { parsePatchFiles, resolveLanguage } from "@pierre/diffs";
26
25
  import { preloadDiffHTML } from "@pierre/diffs/ssr";
27
26
  import { escapeHtml } from "openclaw/plugin-sdk/text-utility-runtime";
27
+ //#region \0rolldown/runtime.js
28
+ var __defProp = Object.defineProperty;
29
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
30
+ var __getOwnPropNames = Object.getOwnPropertyNames;
31
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
32
+ var __exportAll = (all, no_symbols) => {
33
+ let target = {};
34
+ for (var name in all) __defProp(target, name, {
35
+ get: all[name],
36
+ enumerable: true
37
+ });
38
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
39
+ return target;
40
+ };
41
+ var __copyProps = (to, from, except, desc) => {
42
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
43
+ key = keys[i];
44
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
45
+ get: ((k) => from[k]).bind(null, key),
46
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
47
+ });
48
+ }
49
+ return to;
50
+ };
51
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
52
+ //#endregion
28
53
  //#region extensions/diffs/src/types.ts
29
54
  const DIFF_LAYOUTS = ["unified", "split"];
30
55
  const DIFF_MODES = [
@@ -48,6 +73,152 @@ const DIFF_OUTPUT_FORMATS = ["png", "pdf"];
48
73
  const DIFF_ARTIFACT_ID_PATTERN = /^[0-9a-f]{20}$/;
49
74
  const DIFF_ARTIFACT_TOKEN_PATTERN = /^[0-9a-f]{48}$/;
50
75
  //#endregion
76
+ //#region src/gateway/gateway-http-route-contracts.ts
77
+ const GATEWAY_PROBE_ROUTES = /* @__PURE__ */ new Map([
78
+ ["/health", "live"],
79
+ ["/healthz", "live"],
80
+ ["/ready", "ready"],
81
+ ["/readyz", "ready"],
82
+ ["/startup", "startup"],
83
+ ["/startupz", "startup"]
84
+ ]);
85
+ function classifyGatewayProbePath(pathname) {
86
+ for (const [root, status] of GATEWAY_PROBE_ROUTES) {
87
+ if (pathname === root) return status;
88
+ if (pathname.startsWith(`${root}/`)) return "namespace";
89
+ }
90
+ return "outside";
91
+ }
92
+ //#endregion
93
+ //#region packages/normalization-core/src/string-coerce.ts
94
+ /** Trims string input and returns null for non-strings or empty strings. */
95
+ function normalizeNullableString(value) {
96
+ if (typeof value !== "string") return null;
97
+ const trimmed = value.trim();
98
+ return trimmed ? trimmed : null;
99
+ }
100
+ /** Trims string input and returns undefined for non-strings or empty strings. */
101
+ function normalizeOptionalString$1(value) {
102
+ return normalizeNullableString(value) ?? void 0;
103
+ }
104
+ /** Lowercases a normalized optional string. */
105
+ function normalizeOptionalLowercaseString(value) {
106
+ return normalizeOptionalString$1(value)?.toLowerCase();
107
+ }
108
+ /** Lowercases a normalized string or returns an empty string when absent. */
109
+ function normalizeLowercaseStringOrEmpty$1(value) {
110
+ return normalizeOptionalLowercaseString(value) ?? "";
111
+ }
112
+ //#endregion
113
+ //#region src/gateway/security-path.ts
114
+ const MAX_PATH_DECODE_PASSES = 32;
115
+ function normalizePathSeparators(pathname) {
116
+ const collapsed = pathname.replace(/\/{2,}/g, "/");
117
+ if (collapsed.length <= 1) return collapsed;
118
+ return collapsed.replace(/\/+$/, "");
119
+ }
120
+ function resolveDotSegments(pathname) {
121
+ try {
122
+ return new URL(pathname, "http://localhost").pathname;
123
+ } catch {
124
+ return pathname;
125
+ }
126
+ }
127
+ function normalizePathForSecurity(pathname) {
128
+ return normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(resolveDotSegments(pathname))) || "/";
129
+ }
130
+ function pushNormalizedCandidate(candidates, seen, value) {
131
+ const normalized = normalizePathForSecurity(value);
132
+ if (seen.has(normalized)) return;
133
+ seen.add(normalized);
134
+ candidates.push(normalized);
135
+ }
136
+ function buildCanonicalPathCandidates(pathname, maxDecodePasses = MAX_PATH_DECODE_PASSES) {
137
+ const candidates = [];
138
+ const seen = /* @__PURE__ */ new Set();
139
+ pushNormalizedCandidate(candidates, seen, pathname);
140
+ let decoded = pathname;
141
+ let malformedEncoding = false;
142
+ let decodePasses = 0;
143
+ for (let pass = 0; pass < maxDecodePasses; pass++) {
144
+ let nextDecoded;
145
+ try {
146
+ nextDecoded = decodeURIComponent(decoded);
147
+ } catch {
148
+ malformedEncoding = true;
149
+ break;
150
+ }
151
+ if (nextDecoded === decoded) break;
152
+ decodePasses += 1;
153
+ decoded = nextDecoded;
154
+ pushNormalizedCandidate(candidates, seen, decoded);
155
+ }
156
+ let decodePassLimitReached = false;
157
+ if (!malformedEncoding) try {
158
+ decodePassLimitReached = decodeURIComponent(decoded) !== decoded;
159
+ } catch {
160
+ malformedEncoding = true;
161
+ }
162
+ return {
163
+ candidates,
164
+ decodePasses,
165
+ decodePassLimitReached,
166
+ malformedEncoding
167
+ };
168
+ }
169
+ function canonicalizePathForSecurity(pathname) {
170
+ const { candidates, decodePasses, decodePassLimitReached, malformedEncoding } = buildCanonicalPathCandidates(pathname);
171
+ return {
172
+ canonicalPath: candidates[candidates.length - 1] ?? "/",
173
+ candidates,
174
+ decodePasses,
175
+ decodePassLimitReached,
176
+ malformedEncoding,
177
+ rawNormalizedPath: normalizePathSeparators(normalizeLowercaseStringOrEmpty$1(pathname)) || "/"
178
+ };
179
+ }
180
+ const PROTECTED_PLUGIN_ROUTE_PREFIXES = ["/api/channels"];
181
+ //#endregion
182
+ //#region src/gateway/server/plugins-http/path-context.ts
183
+ function normalizeProtectedPrefix(prefix) {
184
+ const collapsed = normalizeLowercaseStringOrEmpty$1(prefix).replace(/\/{2,}/g, "/");
185
+ if (collapsed.length <= 1) return collapsed || "/";
186
+ return collapsed.replace(/\/+$/, "");
187
+ }
188
+ /** Matches a normalized path against an exact protected prefix boundary. */
189
+ function prefixMatchPath(pathname, prefix) {
190
+ return pathname === prefix || pathname.startsWith(`${prefix}/`) || pathname.startsWith(`${prefix}%`);
191
+ }
192
+ const NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES = PROTECTED_PLUGIN_ROUTE_PREFIXES.map(normalizeProtectedPrefix);
193
+ /** Returns true when any decoded path candidate targets a protected route. */
194
+ function isProtectedPluginRoutePathFromContext(context) {
195
+ if (context.candidates.some((candidate) => NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES.some((prefix) => prefixMatchPath(candidate, prefix)))) return true;
196
+ if (context.decodePassLimitReached) return true;
197
+ if (!context.malformedEncoding) return false;
198
+ return NORMALIZED_PROTECTED_PLUGIN_ROUTE_PREFIXES.some((prefix) => prefixMatchPath(context.rawNormalizedPath, prefix));
199
+ }
200
+ /** Builds all security-relevant decoded path candidates for a request path. */
201
+ function resolvePluginRoutePathContext(pathname) {
202
+ const canonical = canonicalizePathForSecurity(pathname);
203
+ return {
204
+ pathname,
205
+ canonicalPath: canonical.canonicalPath,
206
+ candidates: canonical.candidates,
207
+ malformedEncoding: canonical.malformedEncoding,
208
+ decodePassLimitReached: canonical.decodePassLimitReached,
209
+ rawNormalizedPath: canonical.rawNormalizedPath
210
+ };
211
+ }
212
+ //#endregion
213
+ //#region \0openclaw:bundled-sdk:openclaw/plugin-sdk/gateway-config-runtime
214
+ var gateway_config_runtime_exports = /* @__PURE__ */ __exportAll({
215
+ classifyGatewayProbePath: () => classifyGatewayProbePath,
216
+ isProtectedPluginRoutePathFromContext: () => isProtectedPluginRoutePathFromContext,
217
+ resolvePluginRoutePathContext: () => resolvePluginRoutePathContext
218
+ });
219
+ import * as import_openclaw_plugin_sdk_gateway_config_runtime from "openclaw/plugin-sdk/gateway-config-runtime";
220
+ __reExport(gateway_config_runtime_exports, import_openclaw_plugin_sdk_gateway_config_runtime);
221
+ //#endregion
51
222
  //#region extensions/diffs/src/url.ts
52
223
  function buildViewerUrl(params) {
53
224
  const normalizedBase = normalizeViewerBaseUrl(params.baseUrl?.trim() || params.viewerBaseUrl?.trim() || resolveGatewayPublicOrigin(params.config) || resolveGatewayBaseUrl(params.config));
@@ -74,7 +245,7 @@ function normalizeViewerBaseUrl(raw, fieldName = "baseUrl") {
74
245
  }
75
246
  function resolveGatewayBaseUrl(config) {
76
247
  const scheme = config.gateway?.tls?.enabled ? "https" : "http";
77
- const port = resolveGatewayPort(config);
248
+ const port = (0, gateway_config_runtime_exports.resolveGatewayPort)(config);
78
249
  const customHost = config.gateway?.customBindHost?.trim();
79
250
  if (config.gateway?.bind === "custom" && customHost) return `${scheme}://${customHost}:${port}`;
80
251
  return `${scheme}://127.0.0.1:${port}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/diffs",
3
- "version": "2026.8.33",
3
+ "version": "2026.8.35",
4
4
  "description": "OpenClaw read-only diff viewer plugin and file renderer for agents.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,14 +25,14 @@
25
25
  "minHostVersion": ">=2026.4.30"
26
26
  },
27
27
  "compat": {
28
- "pluginApi": ">=2026.8.33"
28
+ "pluginApi": ">=2026.8.35"
29
29
  },
30
30
  "assetScripts": {
31
31
  "build": "node --import tsx ../../scripts/build-diffs-viewer-runtime.mts curated"
32
32
  },
33
33
  "build": {
34
34
  "bundledDist": false,
35
- "openclawVersion": "2026.8.33",
35
+ "openclawVersion": "2026.8.35",
36
36
  "staticAssets": [
37
37
  {
38
38
  "source": "./assets/viewer-runtime.js",
@@ -55,7 +55,7 @@
55
55
  "skills/**"
56
56
  ],
57
57
  "peerDependencies": {
58
- "openclaw": ">=2026.8.33"
58
+ "openclaw": ">=2026.8.35"
59
59
  },
60
60
  "peerDependenciesMeta": {
61
61
  "openclaw": {