Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 59 additions & 63 deletions apps/server/src/wsServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,37 +189,36 @@ function testOpenclawGateway(
error: "Gateway URL is empty.",
};
}
try {
const parsed = new URL(gatewayUrl);
if (!["ws:", "wss:"].includes(parsed.protocol)) {
pushStep(
"URL validation",
"fail",
Date.now() - urlStart,
`Invalid protocol "${parsed.protocol}". Expected ws: or wss:.`,
);
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: `Invalid protocol "${parsed.protocol}".`,
};
}
const parsedUrl = URL.canParse(gatewayUrl) ? new URL(gatewayUrl) : null;
if (!parsedUrl) {
pushStep("URL validation", "fail", Date.now() - urlStart, "Malformed URL.");
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: "Malformed URL.",
};
}
if (!["ws:", "wss:"].includes(parsedUrl.protocol)) {
pushStep(
"URL validation",
"pass",
"fail",
Date.now() - urlStart,
`${parsed.protocol}//${parsed.host}`,
`Invalid protocol "${parsedUrl.protocol}". Expected ws: or wss:.`,
);
} catch {
pushStep("URL validation", "fail", Date.now() - urlStart, "Malformed URL.");
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: "Malformed URL.",
error: `Invalid protocol "${parsedUrl.protocol}".`,
};
}
pushStep(
"URL validation",
"pass",
Date.now() - urlStart,
`${parsedUrl.protocol}//${parsedUrl.host}`,
);

// ── Step 2: WebSocket connect ───────────────────────────────────
const connectStart = Date.now();
Expand Down Expand Up @@ -261,31 +260,25 @@ function testOpenclawGateway(
error: detail,
};
}
ws = wsResult.right;
pushStep(
"WebSocket connect",
"pass",
Date.now() - connectStart,
`Connected in ${Date.now() - connectStart}ms`,
);

// ── Step 3: Authentication ──────────────────────────────────────
if (input.password) {
const authStart = Date.now();
try {
const response = yield* Effect.tryPromise(() =>
sendRpc(ws!, "auth.authenticate", { password: input.password }),
);
if (response.error) {
pushStep(
"Authentication",
"fail",
Date.now() - authStart,
`RPC error ${response.error.code}: ${response.error.message}`,
);
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: `Authentication failed: ${response.error.message}`,
};
}
pushStep("Authentication", "pass", Date.now() - authStart, "Authenticated successfully.");
} catch (err) {
const detail = err instanceof Error ? err.message : "Authentication request failed.";
const authResult = yield* Effect.either(
Effect.tryPromise(() => sendRpc(ws!, "auth.authenticate", { password: input.password })),
);
if (authResult._tag === "Left") {
const detail =
authResult.left instanceof Error
? authResult.left.message
: "Authentication request failed.";
pushStep("Authentication", "fail", Date.now() - authStart, detail);
return {
success: false,
Expand All @@ -294,28 +287,18 @@ function testOpenclawGateway(
error: detail,
};
}
} else {
pushStep("Authentication", "skip", 0, "No password configured.");
}

// ── Step 4: Session create (probe) ──────────────────────────────
const sessionStart = Date.now();
try {
const response = yield* Effect.tryPromise(() =>
sendRpc(ws!, "session.create", { runtimeMode: "headless" }),
);
if (response.error) {
if (authResult.right.error) {
pushStep(
"Session create",
"Authentication",
"fail",
Date.now() - sessionStart,
`RPC error ${response.error.code}: ${response.error.message}`,
Date.now() - authStart,
`RPC error ${authResult.right.error.code}: ${authResult.right.error.message}`,
);
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: `Session creation failed: ${response.error.message}`,
error: `Authentication failed: ${authResult.right.error.message}`,
};
}
const result = (response.result ?? {}) as Record<string, unknown>;
Expand All @@ -327,20 +310,33 @@ function testOpenclawGateway(
};
pushStep(
"Session create",
"pass",
"fail",
Date.now() - sessionStart,
sessionId ? `Session ID: ${sessionId}` : "Session created.",
`RPC error ${sessionResult.right.error.code}: ${sessionResult.right.error.message}`,
);
} catch (err) {
const detail = err instanceof Error ? err.message : "Session creation failed.";
pushStep("Session create", "fail", Date.now() - sessionStart, detail);
return {
success: false,
steps,
totalDurationMs: Date.now() - overallStart,
error: detail,
error: `Session creation failed: ${sessionResult.right.error.message}`,
};
}
const result = (sessionResult.right.result ?? {}) as Record<string, unknown>;
const sessionId = typeof result.sessionId === "string" ? result.sessionId : undefined;
const version = typeof result.version === "string" ? result.version : undefined;
serverInfo = {};
if (version !== undefined) {
serverInfo.version = version;
}
if (sessionId !== undefined) {
serverInfo.sessionId = sessionId;
}
pushStep(
"Session create",
"pass",
Date.now() - sessionStart,
sessionId ? `Session ID: ${sessionId}` : "Session created.",
);

return {
success: true,
Expand Down
2 changes: 2 additions & 0 deletions docs/releases/v0.19.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Release-preflight fixes for server snapshot decoding and exact optional property checks.

## Changes

- Improved release workflow resilience around staged release documentation and optional CLI publishing.
- Fixed snapshot query handling for thread `githubRef` data.
- Fixed `wsServer.ts` type issues blocking strict server typecheck.
Expand All @@ -15,4 +16,5 @@
See the attached assets on this GitHub Release.

## Notes
- See the attached assets on this GitHub Release.
- This release includes release-process fixes landed during the rollout itself.
1 change: 1 addition & 0 deletions docs/releases/v0.19.0/assets.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# OK Code v0.19.0 Assets

This release contains:

- macOS (arm64): `.dmg` and updater manifests where applicable
- Linux (x64): `.AppImage`
- Windows (x64): `.exe`
Expand Down
Loading