@p697/clawket 0.4.3 → 0.4.5

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 +55 -21
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -208,8 +208,8 @@ function normalizeGatewayQrUrl(url) {
208
208
  }
209
209
 
210
210
  // ../../packages/bridge-core/dist/pairing.js
211
- var DEFAULT_REGISTRY_BASE = "https://registry.clawket.ai";
212
- var DEFAULT_REGISTRY_FALLBACK_BASE = "https://clawket-registry.clawket.workers.dev";
211
+ var PACKAGED_DEFAULT_REGISTRY_BASE = "https://registry.clawket.ai"?.trim() ?? "";
212
+ var PACKAGED_DEFAULT_REGISTRY_FALLBACK_BASE = "https://clawket-registry.clawket.workers.dev"?.trim() ?? "";
213
213
  async function pairGateway(input) {
214
214
  const baseUrl = normalizeHttpBase(input.serverUrl);
215
215
  const existing = readPairingConfig();
@@ -358,10 +358,12 @@ function isCloudflareChallengeResponse(response) {
358
358
  function resolveCloudflareChallengeFallbackUrl(url, response) {
359
359
  if (!isCloudflareChallengeResponse(response))
360
360
  return null;
361
+ if (!PACKAGED_DEFAULT_REGISTRY_BASE || !PACKAGED_DEFAULT_REGISTRY_FALLBACK_BASE)
362
+ return null;
361
363
  const requestUrl = new URL(url);
362
- if (requestUrl.origin !== DEFAULT_REGISTRY_BASE)
364
+ if (requestUrl.origin !== PACKAGED_DEFAULT_REGISTRY_BASE)
363
365
  return null;
364
- return `${DEFAULT_REGISTRY_FALLBACK_BASE}${requestUrl.pathname}${requestUrl.search}`;
366
+ return `${PACKAGED_DEFAULT_REGISTRY_FALLBACK_BASE}${requestUrl.pathname}${requestUrl.search}`;
365
367
  }
366
368
  function summarizeFailedResponse(text) {
367
369
  const collapsed = text.replace(/\s+/g, " ").trim();
@@ -1827,7 +1829,7 @@ var BridgeRuntime = class {
1827
1829
  return;
1828
1830
  this.stopped = false;
1829
1831
  this.updateSnapshot({ running: true, gatewayUrl: this.options.gatewayUrl });
1830
- this.log(`runtime starting gatewayId=${this.options.config.gatewayId} gatewayUrl=${this.options.gatewayUrl}`);
1832
+ this.log(`runtime starting gatewayId=${this.options.config.gatewayId} instanceId=${this.options.config.instanceId} gatewayUrl=${redactGatewayWsUrl(this.options.gatewayUrl)}`);
1831
1833
  void this.connectRelay();
1832
1834
  }
1833
1835
  async stop() {
@@ -2030,7 +2032,7 @@ var BridgeRuntime = class {
2030
2032
  }
2031
2033
  try {
2032
2034
  const issued = await issueOpenClawBootstrapToken(parsed.value);
2033
- this.log(`relay bootstrap token issued requestId=${requestId} deviceId=${parsed.value.deviceId} targetClientId=${replyTargetClientId || "<none>"} expiresAtMs=${issued.expiresAtMs}`);
2035
+ this.log(`relay bootstrap token issued requestId=${requestId} targetClientId=${replyTargetClientId || "<none>"} expiresAtMs=${issued.expiresAtMs}`);
2034
2036
  this.sendRelayControl({
2035
2037
  event: "bootstrap.issued",
2036
2038
  requestId,
@@ -2087,7 +2089,7 @@ var BridgeRuntime = class {
2087
2089
  if (this.stopped || !this.isRelayOpen() || this.gatewayConnecting || this.isGatewayOpen() || this.gatewayCloseBoundaryPending)
2088
2090
  return;
2089
2091
  this.gatewayConnecting = true;
2090
- this.log(`gateway connect start url=${this.options.gatewayUrl}`);
2092
+ this.log(`gateway connect start url=${redactGatewayWsUrl(this.options.gatewayUrl)}`);
2091
2093
  const gateway = this.createWebSocket(this.options.gatewayUrl);
2092
2094
  this.gatewaySocket = gateway;
2093
2095
  gateway.once("open", () => {
@@ -2279,13 +2281,13 @@ var BridgeRuntime = class {
2279
2281
  return;
2280
2282
  this.inFlightConnectHandshakes.delete(response.id);
2281
2283
  const detail = response.ok ? "ok=true" : `ok=false errorCode=${response.errorCode ?? "<none>"} errorMessage=${response.errorMessage ?? "<none>"}`;
2282
- this.log(`gateway connect response reqId=${response.id} method=${pending.method} elapsedMs=${Date.now() - pending.startedAtMs} ${detail}`);
2284
+ this.log(`gateway connect response reqId=<redacted> method=${pending.method} elapsedMs=${Date.now() - pending.startedAtMs} ${detail}`);
2283
2285
  }
2284
2286
  clearInFlightConnectHandshakes(reason) {
2285
2287
  if (this.inFlightConnectHandshakes.size === 0)
2286
2288
  return;
2287
2289
  for (const [requestId, pending] of this.inFlightConnectHandshakes.entries()) {
2288
- this.log(`gateway connect response missing reqId=${requestId} method=${pending.method} elapsedMs=${Date.now() - pending.startedAtMs} reason=${reason}`);
2290
+ this.log(`gateway connect response missing reqId=<redacted> method=${pending.method} elapsedMs=${Date.now() - pending.startedAtMs} reason=${reason}`);
2289
2291
  }
2290
2292
  this.inFlightConnectHandshakes.clear();
2291
2293
  }
@@ -2343,7 +2345,7 @@ var BridgeRuntime = class {
2343
2345
  if (pending.slowWarningLogged || elapsedMs < warnDelayMs)
2344
2346
  continue;
2345
2347
  pending.slowWarningLogged = true;
2346
- this.log(`gateway connect still pending reqId=${requestId} method=${pending.method} elapsedMs=${elapsedMs}`);
2348
+ this.log(`gateway connect still pending reqId=<redacted> method=${pending.method} elapsedMs=${elapsedMs}`);
2347
2349
  }
2348
2350
  }
2349
2351
  pushPendingGatewayMessage(message) {
@@ -2401,7 +2403,7 @@ var BridgeRuntime = class {
2401
2403
  this.options.onStatus?.(this.getSnapshot());
2402
2404
  }
2403
2405
  log(line) {
2404
- this.options.onLog?.(line);
2406
+ this.options.onLog?.(sanitizeRuntimeLogLine(line));
2405
2407
  }
2406
2408
  isRelayOpen() {
2407
2409
  return this.relaySocket?.readyState === WebSocket.OPEN;
@@ -2523,7 +2525,7 @@ function patchConnectRequestGatewayAuth(text, openClawInfo) {
2523
2525
  function formatConnectHandshakeMetaForLog(meta) {
2524
2526
  if (!meta)
2525
2527
  return "";
2526
- return ` method=${meta.method} reqId=${meta.id ?? "<none>"} noncePresent=${meta.noncePresent} nonceLength=${meta.nonceLength ?? 0} authFields=${meta.authFields.length > 0 ? meta.authFields.join(",") : "<none>"}`;
2528
+ return ` method=${meta.method} reqId=${meta.id ? "<redacted>" : "<none>"} noncePresent=${meta.noncePresent} nonceLength=${meta.nonceLength ?? 0} authFields=${meta.authFields.length > 0 ? meta.authFields.join(",") : "<none>"}`;
2527
2529
  }
2528
2530
  function parseBootstrapRequestPayload(payload) {
2529
2531
  if (!payload) {
@@ -2600,9 +2602,7 @@ function redactRelayWsUrl(rawUrl) {
2600
2602
  if (parsed.password) {
2601
2603
  parsed.password = "<redacted>";
2602
2604
  }
2603
- if (parsed.searchParams.has("token")) {
2604
- parsed.searchParams.set("token", "<redacted>");
2605
- }
2605
+ stripSensitiveSearchParams(parsed);
2606
2606
  return parsed.toString();
2607
2607
  }
2608
2608
  function redactAuthorizationHeader(value) {
@@ -2611,6 +2611,27 @@ function redactAuthorizationHeader(value) {
2611
2611
  return "<none>";
2612
2612
  return /^Bearer\s+/i.test(trimmed) ? "Bearer <redacted>" : "<redacted>";
2613
2613
  }
2614
+ function sanitizeRuntimeLogLine(line) {
2615
+ return line;
2616
+ }
2617
+ function redactGatewayWsUrl(rawUrl) {
2618
+ const parsed = new URL(rawUrl);
2619
+ if (parsed.username) {
2620
+ parsed.username = "<redacted>";
2621
+ }
2622
+ if (parsed.password) {
2623
+ parsed.password = "<redacted>";
2624
+ }
2625
+ parsed.hostname = "<redacted-host>";
2626
+ stripSensitiveSearchParams(parsed);
2627
+ return parsed.toString();
2628
+ }
2629
+ function stripSensitiveSearchParams(parsed) {
2630
+ const sensitiveKeys = ["token", "password", "gatewayId", "clientId", "requestId", "reqId", "traceId"];
2631
+ for (const key of sensitiveKeys) {
2632
+ parsed.searchParams.delete(key);
2633
+ }
2634
+ }
2614
2635
  function normalizeText(data) {
2615
2636
  if (typeof data === "string")
2616
2637
  return data;
@@ -3088,7 +3109,7 @@ async function main() {
3088
3109
  if ("error" in gatewayAuth) {
3089
3110
  throw new Error(gatewayAuth.error);
3090
3111
  }
3091
- const server = readFlag(args, "--server") ?? readFlag(args, "-s") ?? "https://registry.clawket.ai";
3112
+ const server = resolvePairServer(args);
3092
3113
  const name = readFlag(args, "--name") ?? readFlag(args, "-n") ?? getDefaultBridgeDisplayName();
3093
3114
  const qrFile = readFlag(args, "--qr-file");
3094
3115
  const paired = await pairGateway({
@@ -3261,7 +3282,7 @@ async function main() {
3261
3282
  console.log("Starting bridge runtime. Press Ctrl+C to stop.");
3262
3283
  console.log("");
3263
3284
  } else {
3264
- emitRuntimeLine(`Starting Clawket service runtime for gateway ${config.gatewayId}`);
3285
+ emitRuntimeLine("Starting Clawket service runtime.");
3265
3286
  }
3266
3287
  if (isServiceMode) {
3267
3288
  writeServiceState();
@@ -3274,13 +3295,17 @@ async function main() {
3274
3295
  },
3275
3296
  onStatus: (snapshot) => {
3276
3297
  if (snapshot.lastError) {
3277
- emitRuntimeLine(`[status] relay=${snapshot.relayConnected ? "up" : "down"} gateway=${snapshot.gatewayConnected ? "up" : "down"} clients=${snapshot.clientCount} error=${snapshot.lastError}`);
3298
+ emitRuntimeLine(
3299
+ `[status] relay=${snapshot.relayConnected ? "up" : "down"} gateway=${snapshot.gatewayConnected ? "up" : "down"} clients=${snapshot.clientCount} error=${snapshot.lastError}`
3300
+ );
3278
3301
  return;
3279
3302
  }
3280
- emitRuntimeLine(`[status] relay=${snapshot.relayConnected ? "up" : "down"} gateway=${snapshot.gatewayConnected ? "up" : "down"} clients=${snapshot.clientCount}`);
3303
+ emitRuntimeLine(
3304
+ `[status] relay=${snapshot.relayConnected ? "up" : "down"} gateway=${snapshot.gatewayConnected ? "up" : "down"} clients=${snapshot.clientCount}`
3305
+ );
3281
3306
  },
3282
- onPendingPairRequest: (request) => {
3283
- emitRuntimeLine(`[pair-request] requestId=${request.requestId} deviceId=${request.deviceId || "<unknown>"} name=${request.displayName ?? "<unknown>"}`);
3307
+ onPendingPairRequest: () => {
3308
+ emitRuntimeLine("[pair-request] pending");
3284
3309
  }
3285
3310
  });
3286
3311
  runtime.start();
@@ -3391,6 +3416,15 @@ function readFlag(args, name) {
3391
3416
  function hasFlag(args, name) {
3392
3417
  return args.includes(name);
3393
3418
  }
3419
+ function resolvePairServer(args) {
3420
+ const explicit = readFlag(args, "--server") ?? readFlag(args, "-s");
3421
+ if (explicit?.trim()) return explicit;
3422
+ const envServer = process.env.CLAWKET_REGISTRY_URL?.trim() || "https://registry.clawket.ai"?.trim();
3423
+ if (envServer) return envServer;
3424
+ throw new Error(
3425
+ "No registry server configured. Pass --server https://registry.example.com or set CLAWKET_REGISTRY_URL."
3426
+ );
3427
+ }
3394
3428
  function readPairSubcommand(args) {
3395
3429
  for (const arg of args) {
3396
3430
  if (!arg.startsWith("-")) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@p697/clawket",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Clawket CLI for pairing and running the Relay bridge runtime",
@@ -18,7 +18,7 @@
18
18
  "node": ">=20"
19
19
  },
20
20
  "scripts": {
21
- "build:bundle": "npm run --workspace @clawket/bridge-core build && npm run --workspace @clawket/bridge-runtime build && npx tsup src/index.ts --format esm --platform node --target node20 --clean --no-external @clawket/bridge-core --no-external @clawket/bridge-runtime --external ws --external qrcode-terminal",
21
+ "build:bundle": "npm run --workspace @clawket/bridge-core build && npm run --workspace @clawket/bridge-runtime build && node scripts/build-bundle.mjs",
22
22
  "build": "npm run build:bundle",
23
23
  "typecheck": "npm run --workspace @clawket/bridge-core build && npm run --workspace @clawket/bridge-runtime build && tsc -p tsconfig.json --noEmit",
24
24
  "test": "npm run --workspace @clawket/bridge-core build && npm run --workspace @clawket/bridge-runtime build && vitest run --passWithNoTests",