chore: update appcast and TUI streaming handling
This commit is contained in:
@@ -4,9 +4,9 @@
|
|||||||
<title>Clawdis</title>
|
<title>Clawdis</title>
|
||||||
<item>
|
<item>
|
||||||
<title>2.0.0-beta5</title>
|
<title>2.0.0-beta5</title>
|
||||||
<pubDate>Sat, 03 Jan 2026 06:11:43 +0100</pubDate>
|
<pubDate>Sat, 03 Jan 2026 07:15:16 +0100</pubDate>
|
||||||
<link>https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml</link>
|
<link>https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml</link>
|
||||||
<sparkle:version>2.0.0-beta5</sparkle:version>
|
<sparkle:version>2765</sparkle:version>
|
||||||
<sparkle:shortVersionString>2.0.0-beta5</sparkle:shortVersionString>
|
<sparkle:shortVersionString>2.0.0-beta5</sparkle:shortVersionString>
|
||||||
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
|
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
|
||||||
<description><![CDATA[<h2>Clawdis 2.0.0-beta5</h2>
|
<description><![CDATA[<h2>Clawdis 2.0.0-beta5</h2>
|
||||||
@@ -62,7 +62,8 @@
|
|||||||
<li>CLI: add <code>configure</code>, <code>doctor</code>, and <code>update</code> wizards for ongoing setup, health checks, and modernization.</li>
|
<li>CLI: add <code>configure</code>, <code>doctor</code>, and <code>update</code> wizards for ongoing setup, health checks, and modernization.</li>
|
||||||
<li>CLI: add Signal CLI auto-install from GitHub releases in the wizard and persist wizard run metadata in config.</li>
|
<li>CLI: add Signal CLI auto-install from GitHub releases in the wizard and persist wizard run metadata in config.</li>
|
||||||
<li>CLI: add remote gateway client config (gateway.remote.*) with Bonjour-assisted discovery.</li>
|
<li>CLI: add remote gateway client config (gateway.remote.*) with Bonjour-assisted discovery.</li>
|
||||||
<li>CLI: add <code>clawdis tui</code> gateway-connected terminal UI (local or remote).</li>
|
<li>CLI: enhance <code>clawdis tui</code> with model/session pickers, tool cards, and slash commands (local or remote).</li>
|
||||||
|
<li>Gateway: allow <code>sessions.patch</code> to set per-session model overrides (used by the TUI <code>/model</code> flow).</li>
|
||||||
<li>Skills: allow <code>bun</code> as a node manager for skill installs.</li>
|
<li>Skills: allow <code>bun</code> as a node manager for skill installs.</li>
|
||||||
<li>Skills: add <code>things-mac</code> (Things 3 CLI) for read/search plus add/update via URL scheme.</li>
|
<li>Skills: add <code>things-mac</code> (Things 3 CLI) for read/search plus add/update via URL scheme.</li>
|
||||||
<li>Skills: add Apple Notes + Reminders skills via memo CLI (thanks @tylerwince).</li>
|
<li>Skills: add Apple Notes + Reminders skills via memo CLI (thanks @tylerwince).</li>
|
||||||
@@ -205,7 +206,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p><a href="https://github.com/steipete/clawdis/blob/main/CHANGELOG.md">View full changelog</a></p>
|
<p><a href="https://github.com/steipete/clawdis/blob/main/CHANGELOG.md">View full changelog</a></p>
|
||||||
]]></description>
|
]]></description>
|
||||||
<enclosure url="https://github.com/steipete/clawdis/releases/download/v2.0.0-beta5/Clawdis-2.0.0-beta5.zip" length="72078343" type="application/octet-stream" sparkle:edSignature="xSfMHcYYEktlE+EC8cnM7GJP0oqjfN4EK+oIIcTHvXtgXG7LcBqo4kMQEVrr1kIzCIqQ+7/R6HMd/rWtfkc3Cg=="/>
|
<enclosure url="https://github.com/steipete/clawdis/releases/download/v2.0.0-beta5/Clawdis-2.0.0-beta5.zip" length="145432870" type="application/octet-stream" sparkle:edSignature="qKPcmSx2pAaIYz9NqFp0TY63KrcDlpctUHnNpRs6Q60qQqBWtQycLIhhvhxmGnHupaiEXJfspb/Ad9RgODIzAw=="/>
|
||||||
</item>
|
</item>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
@@ -8,6 +8,7 @@ export class ChatLog extends Container {
|
|||||||
private toolById = new Map<string, ToolExecutionComponent>();
|
private toolById = new Map<string, ToolExecutionComponent>();
|
||||||
private streamingAssistant: AssistantMessageComponent | null = null;
|
private streamingAssistant: AssistantMessageComponent | null = null;
|
||||||
private streamingRunId: string | null = null;
|
private streamingRunId: string | null = null;
|
||||||
|
private streamingText: string | null = null;
|
||||||
private toolsExpanded = false;
|
private toolsExpanded = false;
|
||||||
|
|
||||||
clearAll() {
|
clearAll() {
|
||||||
@@ -15,6 +16,7 @@ export class ChatLog extends Container {
|
|||||||
this.toolById.clear();
|
this.toolById.clear();
|
||||||
this.streamingAssistant = null;
|
this.streamingAssistant = null;
|
||||||
this.streamingRunId = null;
|
this.streamingRunId = null;
|
||||||
|
this.streamingText = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
addSystem(text: string) {
|
addSystem(text: string) {
|
||||||
@@ -30,6 +32,7 @@ export class ChatLog extends Container {
|
|||||||
const component = new AssistantMessageComponent(text);
|
const component = new AssistantMessageComponent(text);
|
||||||
this.streamingAssistant = component;
|
this.streamingAssistant = component;
|
||||||
this.streamingRunId = runId ?? null;
|
this.streamingRunId = runId ?? null;
|
||||||
|
this.streamingText = text;
|
||||||
this.addChild(component);
|
this.addChild(component);
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
@@ -42,17 +45,23 @@ export class ChatLog extends Container {
|
|||||||
this.startAssistant(text, runId);
|
this.startAssistant(text, runId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.streamingText = text;
|
||||||
this.streamingAssistant.setText(text);
|
this.streamingAssistant.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
finalizeAssistant(text: string, runId?: string) {
|
finalizeAssistant(text: string, runId?: string) {
|
||||||
if (this.streamingAssistant && (!runId || runId === this.streamingRunId)) {
|
if (
|
||||||
|
this.streamingAssistant &&
|
||||||
|
(!runId || runId === this.streamingRunId || text === this.streamingText)
|
||||||
|
) {
|
||||||
|
this.streamingText = text;
|
||||||
this.streamingAssistant.setText(text);
|
this.streamingAssistant.setText(text);
|
||||||
} else {
|
} else {
|
||||||
this.startAssistant(text, runId);
|
this.startAssistant(text, runId);
|
||||||
}
|
}
|
||||||
this.streamingAssistant = null;
|
this.streamingAssistant = null;
|
||||||
this.streamingRunId = null;
|
this.streamingRunId = null;
|
||||||
|
this.streamingText = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
startTool(toolCallId: string, toolName: string, args: unknown) {
|
startTool(toolCallId: string, toolName: string, args: unknown) {
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
let currentSessionKey = defaultSession;
|
let currentSessionKey = defaultSession;
|
||||||
let currentSessionId: string | null = null;
|
let currentSessionId: string | null = null;
|
||||||
let activeChatRunId: string | null = null;
|
let activeChatRunId: string | null = null;
|
||||||
|
const finalizedRuns = new Map<string, number>();
|
||||||
let historyLoaded = false;
|
let historyLoaded = false;
|
||||||
let isConnected = false;
|
let isConnected = false;
|
||||||
let toolsExpanded = false;
|
let toolsExpanded = false;
|
||||||
@@ -296,10 +297,30 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
tui.requestRender();
|
tui.requestRender();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const noteFinalizedRun = (runId: string) => {
|
||||||
|
finalizedRuns.set(runId, Date.now());
|
||||||
|
if (finalizedRuns.size <= 200) return;
|
||||||
|
const keepUntil = Date.now() - 10 * 60 * 1000;
|
||||||
|
for (const [key, ts] of finalizedRuns) {
|
||||||
|
if (finalizedRuns.size <= 150) break;
|
||||||
|
if (ts < keepUntil) finalizedRuns.delete(key);
|
||||||
|
}
|
||||||
|
if (finalizedRuns.size > 200) {
|
||||||
|
for (const key of finalizedRuns.keys()) {
|
||||||
|
finalizedRuns.delete(key);
|
||||||
|
if (finalizedRuns.size <= 150) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleChatEvent = (payload: unknown) => {
|
const handleChatEvent = (payload: unknown) => {
|
||||||
if (!payload || typeof payload !== "object") return;
|
if (!payload || typeof payload !== "object") return;
|
||||||
const evt = payload as ChatEvent;
|
const evt = payload as ChatEvent;
|
||||||
if (evt.sessionKey !== currentSessionKey) return;
|
if (evt.sessionKey !== currentSessionKey) return;
|
||||||
|
if (finalizedRuns.has(evt.runId)) {
|
||||||
|
if (evt.state === "delta") return;
|
||||||
|
if (evt.state === "final") return;
|
||||||
|
}
|
||||||
if (evt.state === "delta") {
|
if (evt.state === "delta") {
|
||||||
const text = extractTextFromMessage(evt.message, {
|
const text = extractTextFromMessage(evt.message, {
|
||||||
includeThinking: showThinking,
|
includeThinking: showThinking,
|
||||||
@@ -313,6 +334,7 @@ export async function runTui(opts: TuiOptions) {
|
|||||||
includeThinking: showThinking,
|
includeThinking: showThinking,
|
||||||
});
|
});
|
||||||
chatLog.finalizeAssistant(text || "(no output)", evt.runId);
|
chatLog.finalizeAssistant(text || "(no output)", evt.runId);
|
||||||
|
noteFinalizedRun(evt.runId);
|
||||||
activeChatRunId = null;
|
activeChatRunId = null;
|
||||||
setStatus("idle");
|
setStatus("idle");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user