Compare commits
4 Commits
main
...
shadow/mac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af8ab49f13 | ||
|
|
dcafc78024 | ||
|
|
a1ebc99c7b | ||
|
|
ddc976004a |
@ -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).
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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.")
|
||||||
|
|||||||
@ -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 (
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user