clawdi 0.14.50 → 0.14.52

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.js CHANGED
@@ -1113,7 +1113,7 @@ const managedSocketMetadata = (creds) => {
1113
1113
  `:`
1114
1114
 
1115
1115
  `;a=`${n}${l}${t}
1116
- `}return{existing:n,next:a}}function Eae(e,t){let{existing:n,next:r}=S$(e,t);if(r===n)return e;return le(e,r,{mode:384,dirMode:448}),e}function W3e(e,t){gn(e,"dashboard.basic_auth",{username:t.username,session_ttl_seconds:t.sessionTtlSeconds}),gn(e,"dashboard.public_url",t.publicUrl);let n=ol(e,"plugins.disabled");if(n.exists&&(!Array.isArray(n.value)||n.value.some((i)=>typeof i!=="string")))throw Error("Hermes config field plugins.disabled must be a string array");let r=new Set((n.exists?n.value:[]).filter((i)=>i!=="dashboard_auth/basic"));r.add("dashboard_auth/nous"),r.add("dashboard_auth/self_hosted"),gn(e,"plugins.disabled",[...r].sort())}function $ae(e,t,n,r,i,o){if(t.runtimes[e]?.enabled!==!0)return null;let s=t.locale;if(e==="openclaw"){if(!r)throw Error("OpenClaw official agent workspace is unavailable");return s?Eae(L2(r,"SOUL.md"),Af(s)):null}if(e==="hermes"){if(!o)throw Error("Hermes config command is unavailable");let a=t.hermesDashboardAuth,l=L2(n,".hermes");if(gn(o,"terminal.cwd",i),a)W3e(o,a);if(s)gn(o,"timezone",s.timezone);return s?Eae(L2(l,"SOUL.md"),Af(s)):null}return null}function xae(e,t,n,r,i){let o=hz(t,r,i,n);return t==="hermes"&&n==="dashboard"?G3e(e,o)??o:o}function k$(e,t,n){return hz(e,t,n)}function Pw(e,t,n,r){let i=`runtime ${e}${r?` service ${r}`:""}`,o={...n},s=t?.secretEnv??{};for(let[a,l]of Object.entries(s)){let c=o[a];if(c!==void 0&&c!==l)throw Error(`${i} secretEnv.${a} conflicts with provider secret ref ${c}`);o[a]=l}for(let a of Object.keys(t?.env??{}))if(o[a]!==void 0)throw Error(`${i} defines ${a} in both env and secretEnv`);return o}function G3e(e,t){let n=e.hermesDashboardAuth;if(!n)return t;if(!n.activation.enabled)throw Error("Hermes password authentication is disabled");return{...t??{},prependPath:t?.prependPath??[],env:t?.env??{},secretEnv:{...t?.secretEnv??{},HERMES_DASHBOARD_BASIC_AUTH_PASSWORD:n.passwordSecretRef,HERMES_DASHBOARD_BASIC_AUTH_SECRET:n.sessionSecretRef}}}var b$="<!-- >>> clawdi managed locale >>>",Aw="<!-- <<< clawdi managed locale <<< -->";var R$=_(()=>{ht();sl();jm()});import{createHash as K3e}from"node:crypto";import{chmodSync as U2,chownSync as Z3e,existsSync as Ql,lstatSync as Iae,mkdirSync as Oae,readdirSync as A$,readFileSync as Ew,rmdirSync as Tae,rmSync as z2}from"node:fs";import{dirname as Cs,isAbsolute as J3e,join as Sr}from"node:path";function Y3e(e,t,n,r,i){if(!t)return null;if(r?.status!=="ready")return null;if(!i)return null;return{profileBundlePath:t,envFilePath:e.egressTransparentEnv,transparentPort:Qq,addonPath:i.path,addonSha256:i.sha256,engine:r,systemCaBundle:e.egressSystemCaFile,secretFilePath:n}}function Dae(e){let t=Y3e(e.paths,e.profileBundlePath,e.secretFilePath,e.engine,e.addon);if(!t)return{egressProgram:null,identity:null};return{egressProgram:t,identity:{runtimeUid:e.runtimeIdentity.uid,runtimeGid:e.runtimeIdentity.gid,egressUid:Bb(),egressGid:xc()}}}function F2(e){if(!e.config.enabled)return null;let t=nv(Nae(e.paths),Cs(e.paths.cliManagedBin)),n=e.config.prependPath.join(":"),r={...e.config.env,PATH:n?[n,t].filter(Boolean).join(":"):t},i={};for(let[s,a]of Object.entries(e.config.secretEnv)){let l=zt(e.secretValues??{},a);if(!l)throw Error(`Runtime secret ${a} for ${s} is unavailable.`);r[s]=l,i[s]=l}if(e.egress)Wa(r,{caFile:e.egress.systemCaBundle});let o=e.config.commandPath&&Ql(e.config.commandPath)?e.config.commandPath:e.config.command;return{programKind:"runtime",runtime:e.config.runtime,service:e.config.service,command:o,args:e.config.defaultArgs,cwd:e.config.cwd??e.paths.workspaceRoot,env:r,resolvedSecretEnv:i}}function Wi(e){if(e.programKind==="file-browser")return"clawdi-files";let t=jae(e);if(t)return t;if(!e.service)return`clawdi-${P$(e.runtime)}`;return Q3e(e.runtime,e.service)}function jae(e){return $w(e)?.programName??null}function X3e(e,t,n,r={},i){if(t.programKind==="file-browser")return $t({companion:e.companions?.filebrowser??null,providerProjectionRevision:null});if(t.service)return NX(t);return i(e,t.runtime,n,r[t.runtime]??null)}function Q3e(e,t){let n=x$.find((r)=>r.runtime===e&&r.service===t);if(n)return n.programName;if(e==="hermes"&&t==="dashboard")return"clawdi-hermes-dashboard";return`clawdi-${P$(e)}-${P$(t)}`}function P$(e){return e.replace(/[^A-Za-z0-9_-]+/g,"-")}function Nae(e){return[e.userLocalBin,Sr(e.userHome,".openclaw","bin"),process.env.PATH||"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"].join(":")}function Is(e){return`${P$(e)}.service`}function Cae(e){return Is(Wi(e))}function Mae(e,t){return Sr(e.systemdUserRoot,`${Is(t)}.d`,AP)}function Lae(e){if(/[\r\n]/.test(e))throw Error("systemd unit values must be single-line strings");return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/%/g,"%%").replace(/\$/g,"$$")}"`}function $$(e,t){return[e,...t].map(Lae).join(" ")}function e8e(e,t){return $$(e,["-c",t])}function t8e(e,t,n){return $$("/bin/sh",["-c",'output=$("$1" version 2>&1) || exit $?; case "$output" in *"$2"*) ;; *) exit 65 ;; esac; case "$output" in *"$3"*) ;; *) exit 65 ;; esac',"sh",e,t,n.slice(0,7)])}function ir(e){if(!J3e(e))throw Error(`systemd unit paths must be absolute: ${e}`);if(/[\r\n]/.test(e))throw Error("systemd unit paths must be single-line strings");return e.replace(/\\/g,"\\\\").replace(/%/g,"%%").replace(/ /g,"\\x20").replace(/\t/g,"\\x09")}function n8e(e){return Object.entries(e).map(([t,n])=>`Environment=${Lae(`${t}=${n}`)}`)}function r8e(e,t){return Sr(e.systemdEnvRoot,`${Is(t)}.env`)}function Uae(e){if(/[\r\n]/.test(e))throw Error("systemd environment files only support single-line values");return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function $w(e){return x$.find((t)=>t.runtime===e.runtime&&t.matchesProgram(e))??null}function i8e(e){return x$.find((t)=>Is(t.programName)===e)??null}function H2(e,t){let n=fa(e.runtime,t.userHome);return n&&Wt(n)?n:e.command}function zae(e,t){let n=$w(e);if(!n)return null;let r=Is(n.programName),i=Sr(t.systemdUserRoot,r),o;try{if(!Iae(i).isFile())throw Error(`official ${r} unit is not a regular file`);o=Ew(i)}catch(l){if(l instanceof Error&&"code"in l&&l.code==="ENOENT")return null;throw l}if(RP(o.toString("utf8")))return null;let s=H2(n,t),a=n.runtime==="hermes"?Zt(s):Sv(s,t.userHome,t.userHome);if(!a)throw Error(`official ${r} command revision is unavailable; refusing service reinstall`);return K3e("sha256").update(a).update("\x00").update(o).digest("hex")}function Fae(e,t,n){let r=[],i={};if(!n)return{pending:r,serviceRevisions:i};for(let o of _8e(e)){let s=Is(Wi(o)),a=zae(o,t);if(a)i[s]=a;if(!a)r.push({unitName:s,program:o,serviceRevision:a})}return{pending:r,serviceRevisions:i}}function u8e(e){Pi(e.paths.runRoot,e.paths.systemdRuntimeRoot,{mode:457}),U2(e.paths.systemdRuntimeRoot,457),Pi(e.paths.runRoot,e.paths.systemdEnvRoot,{mode:457}),U2(e.paths.systemdEnvRoot,457);let t=r8e(e.paths,e.name),n=Object.entries(e.env).sort(([i],[o])=>i.localeCompare(o)).map(([i,o])=>{if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i))throw Error(`invalid systemd environment key: ${i}`);return`${i}=${Uae(o)}`}),r=`${kP}
1116
+ `}return{existing:n,next:a}}function Eae(e,t){let{existing:n,next:r}=S$(e,t);if(r===n)return e;return le(e,r,{mode:384,dirMode:448}),e}function W3e(e,t){gn(e,"dashboard.basic_auth",{username:t.username,session_ttl_seconds:t.sessionTtlSeconds}),gn(e,"dashboard.public_url",t.publicUrl);let n=ol(e,"plugins.disabled");if(n.exists&&(!Array.isArray(n.value)||n.value.some((i)=>typeof i!=="string")))throw Error("Hermes config field plugins.disabled must be a string array");let r=new Set((n.exists?n.value:[]).filter((i)=>i!=="dashboard_auth/basic"));r.add("dashboard_auth/nous"),r.add("dashboard_auth/self_hosted"),gn(e,"plugins.disabled",[...r].sort())}function $ae(e,t,n,r,i,o){if(t.runtimes[e]?.enabled!==!0)return null;let s=t.locale;if(e==="openclaw"){if(!r)throw Error("OpenClaw official agent workspace is unavailable");return s?Eae(L2(r,"SOUL.md"),Af(s)):null}if(e==="hermes"){if(!o)throw Error("Hermes config command is unavailable");let a=t.hermesDashboardAuth,l=L2(n,".hermes");if(gn(o,"terminal.cwd",i),a)W3e(o,a);if(s)gn(o,"timezone",s.timezone);return s?Eae(L2(l,"SOUL.md"),Af(s)):null}return null}function xae(e,t,n,r,i){let o=hz(t,r,i,n);return t==="hermes"&&n==="dashboard"?G3e(e,o)??o:o}function k$(e,t,n){return hz(e,t,n)}function Pw(e,t,n,r){let i=`runtime ${e}${r?` service ${r}`:""}`,o={...n},s=t?.secretEnv??{};for(let[a,l]of Object.entries(s)){let c=o[a];if(c!==void 0&&c!==l)throw Error(`${i} secretEnv.${a} conflicts with provider secret ref ${c}`);o[a]=l}for(let a of Object.keys(t?.env??{}))if(o[a]!==void 0)throw Error(`${i} defines ${a} in both env and secretEnv`);return o}function G3e(e,t){let n=e.hermesDashboardAuth;if(!n)return t;if(!n.activation.enabled)throw Error("Hermes password authentication is disabled");return{...t??{},prependPath:t?.prependPath??[],env:t?.env??{},secretEnv:{...t?.secretEnv??{},HERMES_DASHBOARD_BASIC_AUTH_PASSWORD:n.passwordSecretRef,HERMES_DASHBOARD_BASIC_AUTH_SECRET:n.sessionSecretRef}}}var b$="<!-- >>> clawdi managed locale >>>",Aw="<!-- <<< clawdi managed locale <<< -->";var R$=_(()=>{ht();sl();jm()});import{createHash as K3e}from"node:crypto";import{chmodSync as U2,chownSync as Z3e,existsSync as Ql,lstatSync as Iae,mkdirSync as Oae,readdirSync as A$,readFileSync as Ew,rmdirSync as Tae,rmSync as z2}from"node:fs";import{dirname as Cs,isAbsolute as J3e,join as Sr}from"node:path";function Y3e(e,t,n,r,i){if(!t)return null;if(r?.status!=="ready")return null;if(!i)return null;return{profileBundlePath:t,envFilePath:e.egressTransparentEnv,transparentPort:Qq,addonPath:i.path,addonSha256:i.sha256,engine:r,systemCaBundle:e.egressSystemCaFile,secretFilePath:n}}function Dae(e){let t=Y3e(e.paths,e.profileBundlePath,e.secretFilePath,e.engine,e.addon);if(!t)return{egressProgram:null,identity:null};return{egressProgram:t,identity:{runtimeUid:e.runtimeIdentity.uid,runtimeGid:e.runtimeIdentity.gid,egressUid:Bb(),egressGid:xc()}}}function F2(e){if(!e.config.enabled)return null;let t=nv(Nae(e.paths),Cs(e.paths.cliManagedBin)),n=e.config.prependPath.join(":"),r={...e.config.env,PATH:n?[n,t].filter(Boolean).join(":"):t},i={};for(let[s,a]of Object.entries(e.config.secretEnv)){let l=zt(e.secretValues??{},a);if(!l)throw Error(`Runtime secret ${a} for ${s} is unavailable.`);r[s]=l,i[s]=l}if(e.egress)Wa(r,{caFile:e.egress.systemCaBundle});let o=e.config.commandPath&&Ql(e.config.commandPath)?e.config.commandPath:e.config.command;return{programKind:"runtime",runtime:e.config.runtime,service:e.config.service,command:o,args:e.config.defaultArgs,cwd:e.config.cwd??e.paths.workspaceRoot,env:r,resolvedSecretEnv:i}}function Wi(e){if(e.programKind==="file-browser")return"clawdi-files";let t=jae(e);if(t)return t;if(!e.service)return`clawdi-${P$(e.runtime)}`;return Q3e(e.runtime,e.service)}function jae(e){return $w(e)?.programName??null}function X3e(e,t,n,r={},i){if(t.programKind==="file-browser")return $t({companion:e.companions?.filebrowser??null,providerProjectionRevision:null});if(t.service)return NX(t);return i(e,t.runtime,n,r[t.runtime]??null)}function Q3e(e,t){let n=x$.find((r)=>r.runtime===e&&r.service===t);if(n)return n.programName;if(e==="hermes"&&t==="dashboard")return"clawdi-hermes-dashboard";return`clawdi-${P$(e)}-${P$(t)}`}function P$(e){return e.replace(/[^A-Za-z0-9_-]+/g,"-")}function Nae(e){let t=process.env.PATH||"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";return[...new Set([e.userLocalBin,Sr(e.userHome,".openclaw","bin"),...t.split(":")])].join(":")}function Is(e){return`${P$(e)}.service`}function Cae(e){return Is(Wi(e))}function Mae(e,t){return Sr(e.systemdUserRoot,`${Is(t)}.d`,AP)}function Lae(e){if(/[\r\n]/.test(e))throw Error("systemd unit values must be single-line strings");return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/%/g,"%%").replace(/\$/g,"$$")}"`}function $$(e,t){return[e,...t].map(Lae).join(" ")}function e8e(e,t){return $$(e,["-c",t])}function t8e(e,t,n){return $$("/bin/sh",["-c",'output=$("$1" version 2>&1) || exit $?; case "$output" in *"$2"*) ;; *) exit 65 ;; esac; case "$output" in *"$3"*) ;; *) exit 65 ;; esac',"sh",e,t,n.slice(0,7)])}function ir(e){if(!J3e(e))throw Error(`systemd unit paths must be absolute: ${e}`);if(/[\r\n]/.test(e))throw Error("systemd unit paths must be single-line strings");return e.replace(/\\/g,"\\\\").replace(/%/g,"%%").replace(/ /g,"\\x20").replace(/\t/g,"\\x09")}function n8e(e){return Object.entries(e).map(([t,n])=>`Environment=${Lae(`${t}=${n}`)}`)}function r8e(e,t){return Sr(e.systemdEnvRoot,`${Is(t)}.env`)}function Uae(e){if(/[\r\n]/.test(e))throw Error("systemd environment files only support single-line values");return`"${e.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function $w(e){return x$.find((t)=>t.runtime===e.runtime&&t.matchesProgram(e))??null}function i8e(e){return x$.find((t)=>Is(t.programName)===e)??null}function H2(e,t){let n=fa(e.runtime,t.userHome);return n&&Wt(n)?n:e.command}function zae(e,t){let n=$w(e);if(!n)return null;let r=Is(n.programName),i=Sr(t.systemdUserRoot,r),o;try{if(!Iae(i).isFile())throw Error(`official ${r} unit is not a regular file`);o=Ew(i)}catch(l){if(l instanceof Error&&"code"in l&&l.code==="ENOENT")return null;throw l}if(RP(o.toString("utf8")))return null;let s=H2(n,t),a=n.runtime==="hermes"?Zt(s):Sv(s,t.userHome,t.userHome);if(!a)throw Error(`official ${r} command revision is unavailable; refusing service reinstall`);return K3e("sha256").update(a).update("\x00").update(o).digest("hex")}function Fae(e,t,n){let r=[],i={};if(!n)return{pending:r,serviceRevisions:i};for(let o of _8e(e)){let s=Is(Wi(o)),a=zae(o,t);if(a)i[s]=a;if(!a)r.push({unitName:s,program:o,serviceRevision:a})}return{pending:r,serviceRevisions:i}}function u8e(e){Pi(e.paths.runRoot,e.paths.systemdRuntimeRoot,{mode:457}),U2(e.paths.systemdRuntimeRoot,457),Pi(e.paths.runRoot,e.paths.systemdEnvRoot,{mode:457}),U2(e.paths.systemdEnvRoot,457);let t=r8e(e.paths,e.name),n=Object.entries(e.env).sort(([i],[o])=>i.localeCompare(o)).map(([i,o])=>{if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i))throw Error(`invalid systemd environment key: ${i}`);return`${i}=${Uae(o)}`}),r=`${kP}
1117
1117
  ${n.join(`
1118
1118
  `)}
1119
1119
  `;return B2({path:t,content:r,mode:384,dirMode:457,trustedRoot:e.paths.runRoot,owner:e.owner}),t}function B2(e){let t=!1;try{let n=Iae(e.path);t=n.isFile()&&n.nlink===1&&Ew(e.path,"utf8")===e.content}catch{}if(t)U2(e.path,e.mode);else le(e.path,e.content,{mode:e.mode,dirMode:e.dirMode,trustedRoot:e.trustedRoot});if(e.owner==="runtime-user")qg(e.path);else if(Pn())Z3e(e.path,0,0)}function Hae(e){return u8e(e)}function C$(e){return En(e)}function Bae(e){let t=Sr(e.root,Is(e.name)),n=Hae({paths:e.paths,name:e.name,owner:e.owner,env:e.env}),r=[kP,"[Unit]",`Description=${e.description}`,...e.owner==="runtime-user"?["# The environment file is regenerated by convergence each boot; this unit must not start before it exists.",`ConditionPathExists=${ir(n)}`]:[],...e.extraUnitLines??[],"","[Service]",`Type=${e.serviceType??"simple"}`,`WorkingDirectory=${ir(e.cwd)}`,...e.directoryKind==="platform"?[`ConfigurationDirectory=${Wb}`,"ConfigurationDirectoryMode=0700",`StateDirectory=${Wb}`,"StateDirectoryMode=0700",`CacheDirectory=${Wb}`,"CacheDirectoryMode=0700"]:e.directoryKind==="file-browser"?[`StateDirectory=${c0}`,"StateDirectoryMode=0700",`RuntimeDirectory=${c0}`,"RuntimeDirectoryMode=0700"]:[],...e.unitEnv?n8e(e.unitEnv):[],...e.unsetEnvironment?.length?[`UnsetEnvironment=${e.unsetEnvironment.join(" ")}`]:[],...e.extraServiceLines??[],`EnvironmentFile=${ir(n)}`,`ExecStart=${e.execStart??$$(e.command,e.args)}`,...e.restart===!1?[]:["Restart=always","RestartSec=2","KillMode=mixed","TimeoutStopSec=30"],"","[Install]",`WantedBy=${e.wantedBy}`,""],i=()=>{if(e.owner==="runtime-user")Oae(e.root,{recursive:!0});return Pi(e.root,e.root),B2({path:t,content:r.join(`
@@ -13,7 +13,7 @@ import re
13
13
  from datetime import UTC, datetime
14
14
  from pathlib import Path
15
15
  from typing import Any
16
- from urllib.parse import parse_qs, urlsplit
16
+ from urllib.parse import parse_qs, quote, urlsplit
17
17
 
18
18
  try: # pragma: no cover - exercised only under mitmdump.
19
19
  from mitmproxy import ctx, http
@@ -408,13 +408,26 @@ def path_matcher_matches(path: str, matcher: dict[str, Any], secrets: dict[str,
408
408
  secret = secrets.get(str(matcher.get("secretRef", "")))
409
409
  if secret is None:
410
410
  return False
411
- expected = f"{matcher.get('prefix', '')}{secret}{matcher.get('suffix', '')}"
412
- if matcher_type == "secretRefEquals":
413
- return path == expected
414
- return path.startswith(expected)
411
+ matched = match_secret_path_prefix(path, matcher, secret)
412
+ return matched is not None and (
413
+ matcher_type == "secretRefPrefix" or matched.end() == len(path)
414
+ )
415
415
  return False
416
416
 
417
417
 
418
+ def match_secret_path_prefix(
419
+ path: str, matcher: dict[str, Any], secret: str
420
+ ) -> re.Match[str] | None:
421
+ # Encode only credential characters, never path structure or incoming escapes.
422
+ parts = [re.escape(str(matcher.get("prefix", "")))]
423
+ for char in secret:
424
+ encoded = quote(char, safe="/\\")
425
+ literal = re.escape(char)
426
+ parts.append(literal if encoded == char else f"(?:(?i:{encoded})|{literal})")
427
+ parts.append(re.escape(str(matcher.get("suffix", ""))))
428
+ return re.match("".join(parts), path)
429
+
430
+
418
431
  def matcher_matches(value: str | None, matcher: Any, secrets: dict[str, str]) -> bool:
419
432
  if not isinstance(matcher, dict):
420
433
  return False
@@ -523,10 +536,12 @@ def apply_path_replace(request_path: str, rewrite: dict[str, Any], secrets: dict
523
536
  split = urlsplit(request_path or "/")
524
537
  prefix = str(replacement.get("prefix", ""))
525
538
  suffix = str(replacement.get("suffix", ""))
526
- expected = f"{prefix}{placeholder}{suffix}"
527
- if not split.path.startswith(expected):
539
+ matched = match_secret_path_prefix(split.path, replacement, placeholder)
540
+ if matched is None:
528
541
  return request_path
529
- replaced_path = f"{prefix}{actual}{suffix}{split.path[len(expected):]}"
542
+ # Keep path characters, but encode data that could start a query or fragment.
543
+ actual = quote(actual, safe="/:@!$&'()*+,;=")
544
+ replaced_path = f"{prefix}{actual}{suffix}{split.path[matched.end():]}"
530
545
  return f"{replaced_path}?{split.query}" if split.query else replaced_path
531
546
 
532
547
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawdi",
3
- "version": "0.14.50",
3
+ "version": "0.14.52",
4
4
  "description": "The best home for all your AI agents. Run them in the cloud or connect your own—with their context and tools in one place.",
5
5
  "license": "MIT",
6
6
  "type": "module",