shell: dock reorder, fullscreen detection fix, idle-power, sessiond, misc shell work
- Dock drag-to-reorder for pinned apps (insertion gap, quick-slide vs dwell) - Fullscreen detection: scan all windows via HyprlandData.windowList - IdleCoordinator, GlobalStates, Session.qml updates - Deploy script, qmldir, settings, wallpaper, visualizer fixes - sessiond server, memory module updates Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9ccefd6c73
commit
19fe6b1d0e
59 changed files with 19450 additions and 139 deletions
|
|
@ -32,6 +32,12 @@ Singleton {
|
|||
property var messageIDs: []
|
||||
property var messageByID: ({})
|
||||
|
||||
// Which message is currently being spoken by TTS, as an index into
|
||||
// messageIDs (-1 = none). Set by a message's Speak/re-synth button;
|
||||
// auto-cleared when Speech stops. Keyed on the stable messageIndex, so
|
||||
// scrolling back and tapping an older reply still resolves correctly.
|
||||
property int speakingMessageIndex: -1
|
||||
|
||||
// Keys are server-side; the UI's key gate must always pass.
|
||||
readonly property bool currentModelHasApiKey: true
|
||||
readonly property var apiKeysLoaded: true
|
||||
|
|
@ -67,6 +73,15 @@ Singleton {
|
|||
property var currentModelId: Souveraine.currentAgentId
|
||||
property var currentModel: models[currentModelId] || models[modelList[0]]
|
||||
|
||||
// Clear the speaking marker whenever TTS stops — covers natural end of
|
||||
// playback, manual stop, and a new speak() replacing in-flight audio.
|
||||
Connections {
|
||||
target: Speech
|
||||
function onSpeakingChanged() {
|
||||
if (!Speech.speaking) root.speakingMessageIndex = -1
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Souveraine
|
||||
|
||||
|
|
@ -110,7 +125,12 @@ Singleton {
|
|||
}
|
||||
|
||||
function onStreamClosed(exitCode) {
|
||||
root.flushSubconscious();
|
||||
// If a subconscious pass was still active when the stream closed,
|
||||
// retire the Tier-1 ticker (promote to the log, clear the flag).
|
||||
if (root.subconsciousActive) {
|
||||
root.snapshotSubconsciousStream();
|
||||
root.subconsciousActive = false;
|
||||
}
|
||||
if (root.streamingMessage && !root.streamingMessage.done) {
|
||||
if (exitCode !== 0 && root.streamingMessage.content.length === 0) {
|
||||
root.appendToStreaming(Translation.tr("Request failed (curl exit %1) — is the Souveraine server up at %2?").arg(exitCode).arg(Souveraine.serverBase));
|
||||
|
|
@ -199,10 +219,21 @@ Singleton {
|
|||
// ── Streaming message shaping ────────────────────────────────────────
|
||||
property AiMessageData streamingMessage
|
||||
property bool inThinkBlock: false
|
||||
// Raw N+1 output is diagnostic material. The normal chat renders its
|
||||
// parsed surfacing exactly once below; this buffer remains separate from
|
||||
// the chat stream for a future inspector to subscribe to.
|
||||
property string subconsciousBuffer: ""
|
||||
|
||||
// ── Subconscious three-tier visibility ───────────────────────────────
|
||||
// See docs/tasks/subconscious-surfacing-threshold.md. The subconscious's
|
||||
// N+1 pass is shown three ways: a transient live ticker while the pass
|
||||
// runs (Tier 1), a persistent event log after (Tier 2), and rare agency
|
||||
// surfacings in the chat field (Tier 3).
|
||||
//
|
||||
// Tier 1 — live stream fed by subconscious_token/tool_call/tool_result
|
||||
// events. Rendered by SubconsciousTicker; cleared on pass end.
|
||||
property bool subconsciousActive: false
|
||||
property var subconsciousStream: []
|
||||
// Tier 2 — persistent log. The Tier-1 stream is snapshotted here on pass
|
||||
// end, and surfaced events (reflection/archivist/surfacing) are appended.
|
||||
// Rendered by the SubconsciousEventPanel overlay widget.
|
||||
property var subconsciousEvents: []
|
||||
|
||||
function appendToStreaming(text) {
|
||||
if (!root.streamingMessage) return;
|
||||
|
|
@ -210,8 +241,35 @@ Singleton {
|
|||
root.streamingMessage.content += text;
|
||||
}
|
||||
|
||||
function flushSubconscious() {
|
||||
root.subconsciousBuffer = "";
|
||||
// Push a line onto the Tier-1 live stream. kind ∈ token|tool_call|tool_result.
|
||||
function pushSubconsciousStream(kind, text) {
|
||||
const t = String(text ?? "").trim();
|
||||
if (t.length === 0) return;
|
||||
root.subconsciousStream = [...root.subconsciousStream, { kind, text: t }];
|
||||
}
|
||||
|
||||
// Promote the Tier-1 stream into the Tier-2 log as one event, then clear
|
||||
// the live stream. Called when a subconscious pass ends.
|
||||
function snapshotSubconsciousStream() {
|
||||
if (root.subconsciousStream.length === 0) return;
|
||||
root.subconsciousEvents = [...root.subconsciousEvents, {
|
||||
kind: "pass",
|
||||
source: Translation.tr("Subconscious pass"),
|
||||
priority: "",
|
||||
content: root.subconsciousStream.map(e => e.text).join("\n"),
|
||||
timestamp: Date.now(),
|
||||
}];
|
||||
root.subconsciousStream = [];
|
||||
}
|
||||
|
||||
// Append a surfaced event to the Tier-2 log. Used by snapshotSubconsciousStream
|
||||
// (pass end) and by the surfacing/reflection/archivist event handlers.
|
||||
function appendSubconsciousEvent(kind, source, content, priority = "") {
|
||||
const c = String(content ?? "");
|
||||
if (c.length === 0) return;
|
||||
root.subconsciousEvents = [...root.subconsciousEvents, {
|
||||
kind, source, priority, content: c, timestamp: Date.now(),
|
||||
}];
|
||||
}
|
||||
|
||||
function finishStreaming() {
|
||||
|
|
@ -273,17 +331,26 @@ Singleton {
|
|||
: `\n\n*${event.text}*\n\n`);
|
||||
break;
|
||||
case "souveraine_surfacing":
|
||||
// Aster is Annie's name for her subconscious; this surface may
|
||||
// be speaking with Souveraine, Vanguard, or another agent. One
|
||||
// canonical surfacing is shown instead of the raw N+1 token
|
||||
// stream plus a second, agent-specific label.
|
||||
root.addMessage(Translation.tr("**Subconscious surfaces** (%1, %2)\n\n%3").arg(event.source).arg(event.priority).arg(event.content), root.interfaceRole);
|
||||
// Tier 3: routine surfacings no longer pollute the chat field.
|
||||
// Routed to the Tier-2 event panel only. (Aster is Annie's name
|
||||
// for her subconscious; this surface may be Souveraine, Vanguard,
|
||||
// or another agent — one canonical surfacing is shown.)
|
||||
root.appendSubconsciousEvent(
|
||||
"surfacing",
|
||||
Translation.tr("Surfacing (%1)").arg(event.source ?? "?"),
|
||||
event.content,
|
||||
String(event.priority ?? "")
|
||||
);
|
||||
break;
|
||||
case "souveraine_reflection":
|
||||
root.addMessage(Translation.tr("**Reflection**\n\n%1").arg(event.content), root.interfaceRole);
|
||||
root.appendSubconsciousEvent("reflection", Translation.tr("Reflection"), event.content);
|
||||
break;
|
||||
case "souveraine_archivist":
|
||||
root.addMessage(Translation.tr("**Archivist** (pressure %1%)\n\n%2").arg(Math.round(event.pressure * 100)).arg(event.synthesis), root.interfaceRole);
|
||||
root.appendSubconsciousEvent(
|
||||
"archivist",
|
||||
Translation.tr("Archivist (pressure %1%)").arg(Math.round(event.pressure * 100)),
|
||||
event.synthesis
|
||||
);
|
||||
break;
|
||||
case "compaction_warning":
|
||||
root.addMessage(Translation.tr("**Context pressure** — tier %1, %2% full. She can feel the walls.").arg(event.tier).arg(Math.round(event.pressure * 100)), root.interfaceRole);
|
||||
|
|
@ -292,10 +359,24 @@ Singleton {
|
|||
root.tokenCount.total = event.tokens;
|
||||
break;
|
||||
case "subconscious_token":
|
||||
root.subconsciousBuffer += event.content;
|
||||
// Tier 1: live reasoning tokens feed the ticker.
|
||||
root.pushSubconsciousStream("token", event.content);
|
||||
break;
|
||||
case "subconscious_tool_call":
|
||||
root.pushSubconsciousStream("tool_call", `${event.name ?? "tool"}(${event.arguments ?? ""})`);
|
||||
break;
|
||||
case "subconscious_tool_result":
|
||||
root.pushSubconsciousStream("tool_result", `[${event.is_error ? "error" : "ok"}] ${event.name ?? "tool"}: ${event.output ?? ""}`);
|
||||
break;
|
||||
case "subconscious_pass":
|
||||
if (!event.active) root.flushSubconscious();
|
||||
// Pass start: light the Tier-1 ticker. Pass end: promote the
|
||||
// stream into the Tier-2 log, then clear it.
|
||||
if (event.active) {
|
||||
root.subconsciousActive = true;
|
||||
} else {
|
||||
root.snapshotSubconsciousStream();
|
||||
root.subconsciousActive = false;
|
||||
}
|
||||
break;
|
||||
case "subconscious_halt":
|
||||
root.addMessage(Translation.tr("**Halt** (%1) — %2").arg(event.severity).arg(event.reason), root.interfaceRole);
|
||||
|
|
@ -362,7 +443,8 @@ Singleton {
|
|||
root.messageByID = ({});
|
||||
root.streamingMessage = null;
|
||||
root.inThinkBlock = false;
|
||||
root.subconsciousBuffer = "";
|
||||
root.subconsciousActive = false;
|
||||
root.subconsciousStream = [];
|
||||
root.tokenCount.input = -1;
|
||||
root.tokenCount.output = -1;
|
||||
root.tokenCount.total = -1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue