Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c7fd1d0e3 | |||
| 9d8db111ac | |||
| 482cb6ace3 | |||
| 69c1c49a7d | |||
| b1ccf29295 |
@@ -79,8 +79,8 @@ android {
|
|||||||
applicationId "com.ariacockpit"
|
applicationId "com.ariacockpit"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 700
|
versionCode 703
|
||||||
versionName "0.0.7.0"
|
versionName "0.0.7.3"
|
||||||
// Fallback fuer Libraries mit Product Flavors
|
// Fallback fuer Libraries mit Product Flavors
|
||||||
missingDimensionStrategy 'react-native-camera', 'general'
|
missingDimensionStrategy 'react-native-camera', 'general'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aria-cockpit",
|
"name": "aria-cockpit",
|
||||||
"version": "0.0.7.0",
|
"version": "0.0.7.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"android": "react-native run-android",
|
"android": "react-native run-android",
|
||||||
|
|||||||
@@ -283,6 +283,8 @@ const ChatScreen: React.FC = () => {
|
|||||||
|
|
||||||
if (message.type === 'chat') {
|
if (message.type === 'chat') {
|
||||||
const sender = (message.payload.sender as string) || '';
|
const sender = (message.payload.sender as string) || '';
|
||||||
|
const dbgText = ((message.payload.text as string) || '').slice(0, 60);
|
||||||
|
console.log('[Chat] chat-event sender=%s text=%s', sender || '(none)', dbgText);
|
||||||
|
|
||||||
// STT-Ergebnis: Transkribierten Text in die Sprach-Bubble schreiben.
|
// STT-Ergebnis: Transkribierten Text in die Sprach-Bubble schreiben.
|
||||||
// WICHTIG: Nur die ERSTE noch unaufgeloeste Aufnahme matchen — sonst
|
// WICHTIG: Nur die ERSTE noch unaufgeloeste Aufnahme matchen — sonst
|
||||||
@@ -295,6 +297,9 @@ const ChatScreen: React.FC = () => {
|
|||||||
const idx = prev.findIndex(m =>
|
const idx = prev.findIndex(m =>
|
||||||
m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet')
|
m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet')
|
||||||
);
|
);
|
||||||
|
console.log('[Chat] STT-Result: idx=%d text="%s" placeholders=%d',
|
||||||
|
idx, sttText.slice(0, 60),
|
||||||
|
prev.filter(m => m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet')).length);
|
||||||
const newText = `\uD83C\uDFA4 ${sttText}`;
|
const newText = `\uD83C\uDFA4 ${sttText}`;
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
// Defensiv: wenn keine Placeholder im State (z.B. weil sie nie
|
// Defensiv: wenn keine Placeholder im State (z.B. weil sie nie
|
||||||
|
|||||||
+40
-16
@@ -63,24 +63,35 @@
|
|||||||
.log-entry.pipeline-sep { color: #333; margin: 6px 0 2px; }
|
.log-entry.pipeline-sep { color: #333; margin: 6px 0 2px; }
|
||||||
|
|
||||||
.chat-box { background: #080810; border: 1px solid #1E1E2E; border-radius: 6px;
|
.chat-box { background: #080810; border: 1px solid #1E1E2E; border-radius: 6px;
|
||||||
min-height: 120px; max-height: 250px; overflow-y: auto; padding: 8px; margin-bottom: 8px; }
|
min-height: 120px; max-height: 250px; overflow-y: auto;
|
||||||
.chat-msg { margin-bottom: 6px; padding: 6px 10px; border-radius: 6px; font-size: 13px; line-height: 1.5; word-wrap: break-word; }
|
padding: 12px; margin-bottom: 8px; display: flex; flex-direction: column; gap: 8px; }
|
||||||
.chat-msg.sent { background: #0096FF; color: #fff; margin-left: 20%; text-align: right; }
|
.chat-msg { padding: 10px 14px; border-radius: 14px; font-size: 14px; line-height: 1.5;
|
||||||
.chat-msg.received { background: #1E1E2E; margin-right: 20%; }
|
word-wrap: break-word; max-width: 80%; white-space: pre-wrap;
|
||||||
.chat-msg.error { background: #3B1010; color: #FF6B6B; }
|
box-shadow: 0 1px 2px rgba(0,0,0,0.4); }
|
||||||
.chat-msg .meta { font-size: 10px; color: rgba(255,255,255,0.4); margin-top: 2px; }
|
.chat-msg.sent { background: #0096FF; color: #fff; align-self: flex-end;
|
||||||
|
border-bottom-right-radius: 4px; }
|
||||||
|
.chat-msg.received { background: #1E1E2E; color: #E8E8F0; align-self: flex-start;
|
||||||
|
border-bottom-left-radius: 4px; }
|
||||||
|
.chat-msg.error { background: #3B1010; color: #FF6B6B; align-self: flex-start; }
|
||||||
|
.chat-msg .meta { font-size: 10px; color: rgba(255,255,255,0.4); margin-top: 4px;
|
||||||
|
display: block; }
|
||||||
.chat-msg a { color: #66BBFF; text-decoration: underline; }
|
.chat-msg a { color: #66BBFF; text-decoration: underline; }
|
||||||
.chat-msg.sent a { color: #CCEEFF; }
|
.chat-msg.sent a { color: #CCEEFF; }
|
||||||
.chat-msg .chat-media { max-width: 100%; max-height: 200px; border-radius: 4px; margin-top: 4px; cursor: pointer; display: block; }
|
.chat-msg .chat-media { max-width: 100%; max-height: 200px; border-radius: 8px;
|
||||||
|
margin-top: 6px; cursor: pointer; display: block; }
|
||||||
.chat-msg .chat-media:hover { opacity: 0.85; }
|
.chat-msg .chat-media:hover { opacity: 0.85; }
|
||||||
.lightbox-overlay { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.92);
|
.lightbox-overlay { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.92);
|
||||||
z-index:2000; justify-content:center; align-items:center; cursor:pointer; }
|
z-index:2000; justify-content:center; align-items:center; cursor:pointer; }
|
||||||
.lightbox-overlay.open { display:flex; }
|
.lightbox-overlay.open { display:flex; }
|
||||||
.lightbox-overlay img, .lightbox-overlay video { max-width:95vw; max-height:95vh; border-radius:8px; }
|
.lightbox-overlay img, .lightbox-overlay video { max-width:95vw; max-height:95vh; border-radius:8px; }
|
||||||
|
|
||||||
.input-row { display: flex; gap: 6px; }
|
.input-row { display: flex; gap: 6px; align-items: flex-end; }
|
||||||
.input-row input { flex: 1; background: #1E1E2E; border: 1px solid #333; border-radius: 6px;
|
.input-row input, .input-row textarea {
|
||||||
padding: 8px 12px; color: #E0E0F0; font-family: inherit; font-size: 13px; }
|
flex: 1; background: #1E1E2E; border: 1px solid #333; border-radius: 6px;
|
||||||
|
padding: 8px 12px; color: #E0E0F0; font-family: inherit; font-size: 13px;
|
||||||
|
}
|
||||||
|
.input-row textarea { resize: none; min-height: 38px; max-height: 200px; line-height: 1.4;
|
||||||
|
overflow-y: auto; }
|
||||||
|
|
||||||
/* Terminal Modal */
|
/* Terminal Modal */
|
||||||
.modal-overlay { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.85);
|
.modal-overlay { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.85);
|
||||||
@@ -282,7 +293,7 @@
|
|||||||
📎
|
📎
|
||||||
<input type="file" id="diag-file-input" multiple accept="image/*,application/pdf,.doc,.docx,.txt" style="display:none;" onchange="handleDiagFileSelect(this.files)">
|
<input type="file" id="diag-file-input" multiple accept="image/*,application/pdf,.doc,.docx,.txt" style="display:none;" onchange="handleDiagFileSelect(this.files)">
|
||||||
</label>
|
</label>
|
||||||
<input type="text" id="chat-input" placeholder="Nachricht an ARIA..." onpaste="handleDiagPaste(event)">
|
<textarea id="chat-input" placeholder="Nachricht an ARIA... (Enter sendet, Shift+Enter neue Zeile)" rows="2" onpaste="handleDiagPaste(event)" oninput="autoResizeTextarea(this)"></textarea>
|
||||||
<button class="btn" id="btn-gw" onclick="testGateway()">Gateway senden</button>
|
<button class="btn" id="btn-gw" onclick="testGateway()">Gateway senden</button>
|
||||||
<button class="btn" id="btn-rvs" onclick="testRVS()">Via RVS senden</button>
|
<button class="btn" id="btn-rvs" onclick="testRVS()">Via RVS senden</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -300,7 +311,7 @@
|
|||||||
<span style="animation:pulse 1s infinite;">💭</span> <span id="thinking-text-fs">ARIA denkt...</span>
|
<span style="animation:pulse 1s infinite;">💭</span> <span id="thinking-text-fs">ARIA denkt...</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-row" style="margin-top:8px;">
|
<div class="input-row" style="margin-top:8px;">
|
||||||
<input type="text" id="chat-input-fs" placeholder="Nachricht an ARIA..." onkeydown="if(event.key==='Enter'){testRVSFS();event.preventDefault();}">
|
<textarea id="chat-input-fs" placeholder="Nachricht an ARIA... (Enter sendet, Shift+Enter neue Zeile)" rows="2" oninput="autoResizeTextarea(this)"></textarea>
|
||||||
<button class="btn" onclick="testGatewayFS()">Gateway senden</button>
|
<button class="btn" onclick="testGatewayFS()">Gateway senden</button>
|
||||||
<button class="btn" onclick="testRVSFS()">Via RVS senden</button>
|
<button class="btn" onclick="testRVSFS()">Via RVS senden</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -2069,10 +2080,23 @@
|
|||||||
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter-Taste sendet via Gateway
|
// Auto-Resize fuer Textarea — wuchst mit dem Inhalt bis zum max-height
|
||||||
document.getElementById('chat-input').addEventListener('keydown', (e) => {
|
function autoResizeTextarea(el) {
|
||||||
if (e.key === 'Enter') testRVS();
|
el.style.height = 'auto';
|
||||||
});
|
el.style.height = Math.min(el.scrollHeight, 200) + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enter sendet, Shift+Enter macht neue Zeile (chat-Standard).
|
||||||
|
function chatInputKeydown(e, sendFn) {
|
||||||
|
if (e.key === 'Enter' && !e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
sendFn();
|
||||||
|
// Textarea zurueck auf 2 rows setzen
|
||||||
|
e.target.style.height = 'auto';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById('chat-input').addEventListener('keydown', (e) => chatInputKeydown(e, testRVS));
|
||||||
|
document.getElementById('chat-input-fs').addEventListener('keydown', (e) => chatInputKeydown(e, testRVSFS));
|
||||||
|
|
||||||
// Escape schliesst Lightbox
|
// Escape schliesst Lightbox
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
|
|||||||
+14
-1
@@ -716,11 +716,24 @@ function sendToRVS_withResponse(sendType, sendPayload, expectType, clientWs) {
|
|||||||
|
|
||||||
function sendToRVS_raw(msgObj) {
|
function sendToRVS_raw(msgObj) {
|
||||||
if (!RVS_HOST || !RVS_TOKEN) return;
|
if (!RVS_HOST || !RVS_TOKEN) return;
|
||||||
|
const payload = JSON.stringify(msgObj);
|
||||||
|
// Persistente Connection bevorzugen — die ist garantiert connected
|
||||||
|
// und wird vom RVS direkt an alle anderen Clients (App, Bridge) broadcastet.
|
||||||
|
// Frische Connections hatten Race-Probleme: die WS war nach dem send manchmal
|
||||||
|
// schon zu, bevor RVS broadcasten konnte → App-Nachrichten verloren.
|
||||||
|
if (rvsWs && rvsWs.readyState === WebSocket.OPEN) {
|
||||||
|
try {
|
||||||
|
rvsWs.send(payload);
|
||||||
|
return;
|
||||||
|
} catch (err) {
|
||||||
|
log("warn", "rvs", `persistente Verbindung send failed (${err.message}) — Fallback frische WS`);
|
||||||
|
}
|
||||||
|
}
|
||||||
const proto = RVS_TLS === "true" ? "wss" : "ws";
|
const proto = RVS_TLS === "true" ? "wss" : "ws";
|
||||||
const url = `${proto}://${RVS_HOST}:${RVS_PORT}?token=${RVS_TOKEN}`;
|
const url = `${proto}://${RVS_HOST}:${RVS_PORT}?token=${RVS_TOKEN}`;
|
||||||
const freshWs = new WebSocket(url);
|
const freshWs = new WebSocket(url);
|
||||||
freshWs.on("open", () => {
|
freshWs.on("open", () => {
|
||||||
freshWs.send(JSON.stringify(msgObj));
|
freshWs.send(payload);
|
||||||
setTimeout(() => { try { freshWs.close(); } catch (_) {} }, 5000);
|
setTimeout(() => { try { freshWs.close(); } catch (_) {} }, 5000);
|
||||||
});
|
});
|
||||||
freshWs.on("error", () => {});
|
freshWs.on("error", () => {});
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ services:
|
|||||||
command: >-
|
command: >-
|
||||||
sh -c "apk add --no-cache openssh-client bash curl &&
|
sh -c "apk add --no-cache openssh-client bash curl &&
|
||||||
npm install -g @anthropic-ai/claude-code claude-max-api-proxy &&
|
npm install -g @anthropic-ai/claude-code claude-max-api-proxy &&
|
||||||
DIST=$(find /usr/local/lib -path '*/claude-max-api-proxy/dist' -type d | head -1) &&
|
DIST=$$(find /usr/local/lib -path '*/claude-max-api-proxy/dist' -type d | head -1) &&
|
||||||
sed -i 's/startServer({ port })/startServer({ port, host: process.env.HOST || \"127.0.0.1\" })/' $$DIST/server/standalone.js &&
|
sed -i 's/startServer({ port })/startServer({ port, host: process.env.HOST || \"127.0.0.1\" })/' $$DIST/server/standalone.js &&
|
||||||
sed -i 's/if (model\.includes/if ((model||\"claude-sonnet-4\").includes/g' $$DIST/adapter/cli-to-openai.js &&
|
sed -i 's/if (model\.includes/if ((model||\"claude-sonnet-4\").includes/g' $$DIST/adapter/cli-to-openai.js &&
|
||||||
sed -i '1i\\function _t(c){return typeof c===\"string\"?c:Array.isArray(c)?c.filter(function(b){return b.type===\"text\"}).map(function(b){return b.text||\"\"}).join(\"\"):String(c)}' $$DIST/adapter/openai-to-cli.js &&
|
sed -i '1i\\function _t(c){return typeof c===\"string\"?c:Array.isArray(c)?c.filter(function(b){return b.type===\"text\"}).map(function(b){return b.text||\"\"}).join(\"\"):String(c)}' $$DIST/adapter/openai-to-cli.js &&
|
||||||
|
|||||||
Reference in New Issue
Block a user