Compare commits

...

4 Commits

Author SHA1 Message Date
Peter Steinberger
af8ab49f13 fix: satisfy discord and gateway typing 2026-01-03 02:52:04 +01:00
Peter Steinberger
dcafc78024 docs: note onboarding scroll gutter 2026-01-03 02:47:56 +01:00
Peter Steinberger
a1ebc99c7b fix: respect onboarding scroll indicator preference 2026-01-03 02:47:34 +01:00
Shadow
ddc976004a macOS: add onboarding scroll gutter 2026-01-03 02:47:31 +01:00
5 changed files with 22 additions and 10 deletions

View File

@ -55,6 +55,7 @@
### Fixes ### Fixes
- Gog calendar: format date ranges as RFC 3339 with timezone to satisfy Google Calendar API (thanks @jayhickey). - Gog calendar: format date ranges as RFC 3339 with timezone to satisfy Google Calendar API (thanks @jayhickey).
- macOS onboarding: add scrollable page gutter for overflowing content (#105) — thanks @thewilloftheshadow.
- Chat UI: keep the chat scrolled to the latest message after switching sessions. - Chat UI: keep the chat scrolled to the latest message after switching sessions.
- Auto-reply: stream completed reply blocks as soon as they finish (configurable default + break); skip empty tool-only blocks unless verbose. - Auto-reply: stream completed reply blocks as soon as they finish (configurable default + break); skip empty tool-only blocks unless verbose.
- Discord: avoid duplicate sends when block streaming is enabled (race with typing hook). - Discord: avoid duplicate sends when block streaming is enabled (race with typing hook).

View File

@ -133,10 +133,16 @@ extension OnboardingView {
} }
func onboardingPage(@ViewBuilder _ content: () -> some View) -> some View { func onboardingPage(@ViewBuilder _ content: () -> some View) -> some View {
VStack(spacing: 16) { let scrollIndicatorGutter: CGFloat = 18
content() return ScrollView {
Spacer() VStack(spacing: 16) {
content()
Spacer(minLength: 0)
}
.frame(maxWidth: .infinity, alignment: .top)
.padding(.trailing, scrollIndicatorGutter)
} }
.scrollIndicators(.automatic)
.padding(.horizontal, 28) .padding(.horizontal, 28)
.frame(width: self.pageWidth, alignment: .top) .frame(width: self.pageWidth, alignment: .top)
} }

View File

@ -442,7 +442,7 @@ extension OnboardingView {
} }
func permissionsPage() -> some View { func permissionsPage() -> some View {
self.onboardingPage { return self.onboardingPage {
Text("Grant permissions") Text("Grant permissions")
.font(.largeTitle.weight(.semibold)) .font(.largeTitle.weight(.semibold))
Text("These macOS permissions let Clawdis automate apps and capture context on this Mac.") Text("These macOS permissions let Clawdis automate apps and capture context on this Mac.")

View File

@ -396,6 +396,11 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
MediaType: media?.contentType, MediaType: media?.contentType,
MediaUrl: media?.path, MediaUrl: media?.path,
}; };
const replyTarget = ctxPayload.To ?? undefined;
if (!replyTarget) {
runtime.error?.(danger("discord: missing reply target"));
return;
}
if (isDirectMessage) { if (isDirectMessage) {
const sessionCfg = cfg.session; const sessionCfg = cfg.session;
@ -430,7 +435,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
.then(async () => { .then(async () => {
await deliverReplies({ await deliverReplies({
replies: [payload], replies: [payload],
target: ctxPayload.To, target: replyTarget,
token, token,
runtime, runtime,
replyToMode, replyToMode,
@ -473,7 +478,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
await deliverReplies({ await deliverReplies({
replies, replies,
target: ctxPayload.To, target: replyTarget,
token, token,
runtime, runtime,
replyToMode, replyToMode,
@ -482,7 +487,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) {
didSendReply = true; didSendReply = true;
if (isVerbose()) { if (isVerbose()) {
logVerbose( logVerbose(
`discord: delivered ${replies.length} reply${replies.length === 1 ? "" : "ies"} to ${ctxPayload.To}`, `discord: delivered ${replies.length} reply${replies.length === 1 ? "" : "ies"} to ${replyTarget}`,
); );
} }
if ( if (

View File

@ -27,6 +27,7 @@ export async function callGateway<T = unknown>(
const config = loadConfig(); const config = loadConfig();
const isRemoteMode = config.gateway?.mode === "remote"; const isRemoteMode = config.gateway?.mode === "remote";
const remote = isRemoteMode ? config.gateway?.remote : undefined; const remote = isRemoteMode ? config.gateway?.remote : undefined;
const authToken = config.gateway?.auth?.token;
const url = const url =
(typeof opts.url === "string" && opts.url.trim().length > 0 (typeof opts.url === "string" && opts.url.trim().length > 0
? opts.url.trim() ? opts.url.trim()
@ -44,9 +45,8 @@ export async function callGateway<T = unknown>(
? remote.token.trim() ? remote.token.trim()
: undefined : undefined
: process.env.CLAWDIS_GATEWAY_TOKEN?.trim() || : process.env.CLAWDIS_GATEWAY_TOKEN?.trim() ||
(typeof config.gateway?.auth?.token === "string" && (typeof authToken === "string" && authToken.trim().length > 0
config.gateway.auth.token.trim().length > 0 ? authToken.trim()
? config.gateway.auth.token.trim()
: undefined)); : undefined));
const password = const password =
(typeof opts.password === "string" && opts.password.trim().length > 0 (typeof opts.password === "string" && opts.password.trim().length > 0