82 lines
2.8 KiB
QML
82 lines
2.8 KiB
QML
|
|
import qs
|
||
|
|
import qs.services
|
||
|
|
import qs.modules.common
|
||
|
|
import qs.modules.common.widgets
|
||
|
|
import qs.modules.common.functions
|
||
|
|
import QtQuick
|
||
|
|
import QtQuick.Layouts
|
||
|
|
|
||
|
|
// Tier 1 of the subconscious three-tier visibility design (see
|
||
|
|
// docs/tasks/subconscious-surfacing-threshold.md): a transient, fading line
|
||
|
|
// that shows the subconscious's live reasoning/tools while its N+1 pass runs.
|
||
|
|
// Visible only while Ai.subconsciousActive; fed by Ai.subconsciousStream;
|
||
|
|
// cleared (and snapshotted to the Tier-2 log) when the pass ends.
|
||
|
|
Rectangle {
|
||
|
|
id: root
|
||
|
|
Layout.fillWidth: true
|
||
|
|
implicitHeight: row.implicitHeight + 2 * root.padding
|
||
|
|
radius: Appearance.rounding.small
|
||
|
|
color: Appearance.colors.colLayer2
|
||
|
|
visible: Ai.subconsciousActive && Ai.subconsciousStream.length > 0
|
||
|
|
opacity: visible ? 1 : 0
|
||
|
|
|
||
|
|
property real padding: 6
|
||
|
|
|
||
|
|
Behavior on opacity {
|
||
|
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||
|
|
}
|
||
|
|
Behavior on implicitHeight {
|
||
|
|
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fader: retire the oldest line a few seconds after it arrives so the
|
||
|
|
// ticker reads as a live stream, not an accumulating log. The full stream
|
||
|
|
// is snapshotted to Ai.subconsciousEvents on pass end regardless.
|
||
|
|
Timer {
|
||
|
|
interval: 4000
|
||
|
|
repeat: true
|
||
|
|
running: root.visible
|
||
|
|
onTriggered: {
|
||
|
|
if (Ai.subconsciousStream.length > 1)
|
||
|
|
Ai.subconsciousStream = Ai.subconsciousStream.slice(1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
RowLayout {
|
||
|
|
id: row
|
||
|
|
anchors.fill: parent
|
||
|
|
anchors.margins: root.padding
|
||
|
|
spacing: root.padding
|
||
|
|
|
||
|
|
MaterialSymbol {
|
||
|
|
Layout.alignment: Qt.AlignVCenter
|
||
|
|
iconSize: Appearance.font.pixelSize.larger
|
||
|
|
text: "psychology"
|
||
|
|
color: Appearance.colors.colSubtext
|
||
|
|
NumberAnimation on opacity {
|
||
|
|
// gentle pulse while the pass runs
|
||
|
|
from: 0.5; to: 1; duration: 1200
|
||
|
|
running: root.visible; loops: Animation.Infinite
|
||
|
|
easing.type: Easing.InOutSine
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
StyledText {
|
||
|
|
Layout.fillWidth: true
|
||
|
|
Layout.alignment: Qt.AlignVCenter
|
||
|
|
text: {
|
||
|
|
const s = Ai.subconsciousStream;
|
||
|
|
if (s.length === 0) return "";
|
||
|
|
const last = s[s.length - 1];
|
||
|
|
const tag = last.kind === "tool_call" || last.kind === "tool_result"
|
||
|
|
? Translation.tr("tool") : Translation.tr("thinking");
|
||
|
|
return `${tag} · ${last.text}`;
|
||
|
|
}
|
||
|
|
color: Appearance.colors.colSubtext
|
||
|
|
font.pixelSize: Appearance.font.pixelSize.small
|
||
|
|
elide: Text.ElideRight
|
||
|
|
maximumLineCount: 2
|
||
|
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|