@olares/lares-mobile 0.15.34 → 0.15.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/App.vue +3 -1
- package/src/chat/ApprovalCard.vue +138 -0
- package/src/desktop/DesktopComposer.vue +10 -26
- package/src/desktop/DesktopQueue.vue +5 -1
- package/src/mobile/MobileShell.vue +18 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olares/lares-mobile",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.35",
|
|
4
4
|
"description": "Lares chat component for LarePass",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"vue": "^3.2.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@olares/lares-core": "0.15.
|
|
31
|
+
"@olares/lares-core": "0.15.35",
|
|
32
32
|
"markdown-it": "^14.3.0"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/App.vue
CHANGED
|
@@ -102,6 +102,7 @@
|
|
|
102
102
|
@pick-command="pickCommand"
|
|
103
103
|
@toggle-speak="toggleSpeak"
|
|
104
104
|
@dismiss-speak="speakNotice = ''"
|
|
105
|
+
@answer-approval="answerApproval"
|
|
105
106
|
/>
|
|
106
107
|
<LaresVoicePanel v-if="voicePanelState" :view="voicePanelState" :t="t"
|
|
107
108
|
@close="runVoicePanel('close')" @edit="voicePanel.edit($event)" @preset="voicePanel.selectPreset($event, true).catch(() => {})"
|
|
@@ -154,6 +155,7 @@ import {
|
|
|
154
155
|
effortSwitchSelection,
|
|
155
156
|
} from "@olares/lares-core/router/session-model";
|
|
156
157
|
import { messageFromCode } from "@olares/lares-core/i18n/t";
|
|
158
|
+
import { presentApproval } from "@olares/lares-core/larepass/approval";
|
|
157
159
|
import { parseAskUserQuestions, singleSelectAnswer } from "@olares/lares-core/larepass/questions";
|
|
158
160
|
import { applyCommand } from "@olares/lares-core/larepass/commands";
|
|
159
161
|
import { permissionOption, presetDescription, presetLabel } from "@olares/lares-core/larepass/permissions";
|
|
@@ -785,7 +787,7 @@ export default {
|
|
|
785
787
|
this.queue = snap.queue ?? [];
|
|
786
788
|
this.question = snap.question || null;
|
|
787
789
|
if (!this.question) this.questionBusy = false;
|
|
788
|
-
this.approval = snap.approval
|
|
790
|
+
this.approval = presentApproval(snap.approval, snap.items, this.locale);
|
|
789
791
|
if (!this.approval) this.approvalBusy = false;
|
|
790
792
|
if (this.pendingUser && snap.items.some((row) => row.type === "user" && row.text === this.pendingUser)) {
|
|
791
793
|
this.pendingUser = "";
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section
|
|
3
|
+
class="lares-approval"
|
|
4
|
+
:aria-busy="busy ? 'true' : 'false'"
|
|
5
|
+
@keydown="onKeydown"
|
|
6
|
+
>
|
|
7
|
+
<div class="lares-approval__strip">
|
|
8
|
+
<span aria-hidden="true" />
|
|
9
|
+
{{ t("approval.waiting") }}
|
|
10
|
+
</div>
|
|
11
|
+
<div
|
|
12
|
+
class="lares-approval__body"
|
|
13
|
+
tabindex="0"
|
|
14
|
+
role="group"
|
|
15
|
+
:aria-label="t('approval.detail')"
|
|
16
|
+
>
|
|
17
|
+
<p class="lares-approval__headline">{{ headline }}</p>
|
|
18
|
+
<p v-if="approval.command" class="lares-approval__command">{{ approval.command }}</p>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="lares-approval__actions">
|
|
21
|
+
<button type="button" :disabled="busy" @click="$emit('answer', 'rejected')">
|
|
22
|
+
{{ t("approval.reject") }}
|
|
23
|
+
</button>
|
|
24
|
+
<button type="button" :disabled="busy" @click="$emit('answer', 'allowed-once')">
|
|
25
|
+
{{ t("approval.allowOnce") }}
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
</section>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script>
|
|
32
|
+
export default {
|
|
33
|
+
name: "LaresApprovalCard",
|
|
34
|
+
props: {
|
|
35
|
+
approval: { type: Object, required: true },
|
|
36
|
+
busy: { type: Boolean, default: false },
|
|
37
|
+
t: { type: Function, required: true },
|
|
38
|
+
},
|
|
39
|
+
emits: ["answer"],
|
|
40
|
+
computed: {
|
|
41
|
+
headline() {
|
|
42
|
+
return this.approval.reason || this.t("approval.escalation", { toolName: this.approval.toolName });
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
methods: {
|
|
46
|
+
onKeydown(event) {
|
|
47
|
+
const target = event.target;
|
|
48
|
+
if (event.defaultPrevented || this.busy) return;
|
|
49
|
+
if (event.key !== "Enter" && event.key !== "Escape") return;
|
|
50
|
+
if (target?.closest?.("input, textarea, select, [contenteditable='true']")) return;
|
|
51
|
+
if (event.key === "Enter" && target?.closest?.("button, a[href], [role='button']")) return;
|
|
52
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey || event.repeat) return;
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
this.$emit("answer", event.key === "Enter" ? "allowed-once" : "rejected");
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<style scoped>
|
|
61
|
+
.lares-approval {
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
border: 1px solid var(--q-orange-default);
|
|
64
|
+
border-radius: 14px;
|
|
65
|
+
background: var(--q-background-1);
|
|
66
|
+
box-shadow: 0 1px 3px rgb(0 0 0 / 8%);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.lares-approval__strip {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
gap: 8px;
|
|
73
|
+
padding: 10px 16px;
|
|
74
|
+
background: var(--q-orange-alpha);
|
|
75
|
+
color: var(--q-orange-default);
|
|
76
|
+
font-size: 13px;
|
|
77
|
+
line-height: 18px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.lares-approval__strip span {
|
|
81
|
+
width: 6px;
|
|
82
|
+
height: 6px;
|
|
83
|
+
flex: none;
|
|
84
|
+
border-radius: 50%;
|
|
85
|
+
background: var(--q-orange-default);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.lares-approval__body {
|
|
89
|
+
display: flex;
|
|
90
|
+
max-height: 160px;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
gap: 6px;
|
|
93
|
+
overflow-y: auto;
|
|
94
|
+
padding: 12px 16px 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.lares-approval__headline {
|
|
98
|
+
margin: 0;
|
|
99
|
+
color: var(--q-ink-1);
|
|
100
|
+
font-size: 15px;
|
|
101
|
+
font-weight: 500;
|
|
102
|
+
line-height: 24px;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.lares-approval__command {
|
|
106
|
+
margin: 0;
|
|
107
|
+
color: var(--q-ink-3);
|
|
108
|
+
font: 400 13px/20px ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
109
|
+
word-break: break-all;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.lares-approval__actions {
|
|
113
|
+
display: flex;
|
|
114
|
+
justify-content: flex-end;
|
|
115
|
+
gap: 8px;
|
|
116
|
+
padding: 14px 16px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.lares-approval__actions button {
|
|
120
|
+
height: 32px;
|
|
121
|
+
border: 1px solid var(--q-separator);
|
|
122
|
+
border-radius: 7px;
|
|
123
|
+
padding: 0 13px;
|
|
124
|
+
background: transparent;
|
|
125
|
+
color: var(--q-ink-2);
|
|
126
|
+
font: inherit;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.lares-approval__actions button:last-child {
|
|
130
|
+
border-color: transparent;
|
|
131
|
+
background: var(--q-blue-default);
|
|
132
|
+
color: var(--q-ink-on-brand);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.lares-approval__actions button:disabled {
|
|
136
|
+
opacity: 0.45;
|
|
137
|
+
}
|
|
138
|
+
</style>
|
|
@@ -139,23 +139,14 @@
|
|
|
139
139
|
</div>
|
|
140
140
|
|
|
141
141
|
<Transition name="lares-panel" mode="out-in">
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
<div class="desktop-composer__approval-actions">
|
|
151
|
-
<button type="button" :disabled="state.approvalBusy" @click="$emit('answer-approval', 'rejected')">
|
|
152
|
-
{{ t("approval.reject") }}
|
|
153
|
-
</button>
|
|
154
|
-
<button type="button" :disabled="state.approvalBusy" @click="$emit('answer-approval', 'allowed-once')">
|
|
155
|
-
{{ t("approval.allowOnce") }}
|
|
156
|
-
</button>
|
|
157
|
-
</div>
|
|
158
|
-
</div>
|
|
142
|
+
<LaresApprovalCard
|
|
143
|
+
v-if="state.approval"
|
|
144
|
+
key="approval"
|
|
145
|
+
:approval="state.approval"
|
|
146
|
+
:busy="state.approvalBusy"
|
|
147
|
+
:t="t"
|
|
148
|
+
@answer="$emit('answer-approval', $event)"
|
|
149
|
+
/>
|
|
159
150
|
<LaresDesktopQuestions
|
|
160
151
|
v-else-if="state.question?.questions?.length"
|
|
161
152
|
key="questions"
|
|
@@ -480,6 +471,7 @@ import { DEFAULT_WORKSPACE_TITLE } from "@olares/lares-core/workspace/constants"
|
|
|
480
471
|
import { activeReferenceToken, insertReference } from "@olares/lares-core/larepass/references";
|
|
481
472
|
import { draftImageStatus } from "@olares/lares-core/files/draft-images";
|
|
482
473
|
import LaresVoiceInput from "../chat/VoiceInput.vue";
|
|
474
|
+
import LaresApprovalCard from "../chat/ApprovalCard.vue";
|
|
483
475
|
import LaresDesktopQueue from "./DesktopQueue.vue";
|
|
484
476
|
import LaresDesktopQuestions from "./DesktopQuestions.vue";
|
|
485
477
|
import LaresDesktopContextMeter from "./DesktopContextMeter.vue";
|
|
@@ -542,7 +534,7 @@ const PermissionIcon = {
|
|
|
542
534
|
|
|
543
535
|
export default {
|
|
544
536
|
name: "LaresDesktopComposer",
|
|
545
|
-
components: { LaresVoiceInput, LaresDesktopContextMeter, LaresDesktopGoal, LaresDesktopQuestions, LaresDesktopQueue, LaresDesktopTodos, LaresPcDialog, LaresPcPopover, LaresPcTooltip, ChevronIcon, CheckIcon, PlusIcon, PaperclipIcon, ArrowIcon, StopIcon, CloseIcon, MicIcon, PermissionIcon },
|
|
537
|
+
components: { LaresApprovalCard, LaresVoiceInput, LaresDesktopContextMeter, LaresDesktopGoal, LaresDesktopQuestions, LaresDesktopQueue, LaresDesktopTodos, LaresPcDialog, LaresPcPopover, LaresPcTooltip, ChevronIcon, CheckIcon, PlusIcon, PaperclipIcon, ArrowIcon, StopIcon, CloseIcon, MicIcon, PermissionIcon },
|
|
546
538
|
props: {
|
|
547
539
|
state: { type: Object, required: true },
|
|
548
540
|
t: { type: Function, required: true },
|
|
@@ -959,14 +951,6 @@ export default {
|
|
|
959
951
|
.desktop-composer__reference-item[data-selected="true"] { background:var(--q-background-hover); }
|
|
960
952
|
.desktop-composer__reference-name { max-width:40%; flex:none; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
961
953
|
.desktop-composer__reference-path { min-width:0; flex:1; overflow:hidden; color:var(--q-ink-3); text-overflow:ellipsis; white-space:nowrap; }
|
|
962
|
-
.desktop-composer__approval { overflow:hidden; border:1px solid var(--q-separator); border-radius:14px; background:var(--q-background-2); box-shadow:0 1px 3px rgb(0 0 0 / 8%); }
|
|
963
|
-
.desktop-composer__approval-strip { display:flex; height:30px; align-items:center; gap:7px; padding:0 12px; background:var(--q-background-3); color:var(--q-ink-3); font-size:12px; }
|
|
964
|
-
.desktop-composer__approval-strip span { width:6px; height:6px; border-radius:50%; background:var(--q-orange-default); }
|
|
965
|
-
.desktop-composer__approval-body { max-height:96px; overflow:auto; padding:14px 16px; color:var(--q-ink-1); font-size:14px; line-height:20px; }
|
|
966
|
-
.desktop-composer__approval-actions { display:flex; justify-content:flex-end; gap:8px; padding:8px 12px 12px; }
|
|
967
|
-
.desktop-composer__approval-actions button { height:32px; border:1px solid var(--q-separator); border-radius:7px; padding:0 13px; background:transparent; color:var(--q-ink-2); font:inherit; cursor:pointer; }
|
|
968
|
-
.desktop-composer__approval-actions button:last-child { border-color:transparent; background:var(--q-blue-default); color:var(--q-ink-on-brand); }
|
|
969
|
-
.desktop-composer__approval-actions button:disabled { opacity:.45; cursor:default; }
|
|
970
954
|
.desktop-composer__attachments { display:flex; gap:8px; overflow-x:auto; padding:0 0 8px 2px; }
|
|
971
955
|
.desktop-composer__attachments figure { position:relative; width:64px; height:64px; flex:0 0 64px; overflow:hidden; margin:0; border:1px solid var(--q-separator); border-radius:9px; background:var(--q-background-3); }
|
|
972
956
|
.desktop-composer__attachments img { width:100%; height:100%; object-fit:cover; transition:opacity .22s ease; }
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="rows.length" class="desktop-queue lares-queue-in">
|
|
2
|
+
<div v-if="rows.length" class="desktop-queue lares-queue-in" :data-tone="tone">
|
|
3
3
|
<div class="desktop-queue__panel">
|
|
4
4
|
<button
|
|
5
5
|
v-if="rows.length > 1"
|
|
@@ -128,6 +128,7 @@ export default {
|
|
|
128
128
|
items: { type: Array, default: () => [] },
|
|
129
129
|
running: { type: Boolean, default: false },
|
|
130
130
|
busy: { type: String, default: "" },
|
|
131
|
+
tone: { type: String, default: "" },
|
|
131
132
|
t: { type: Function, required: true },
|
|
132
133
|
},
|
|
133
134
|
emits: ["action"],
|
|
@@ -198,4 +199,7 @@ export default {
|
|
|
198
199
|
:deep(.desktop-queue__action:disabled) { opacity:.45; cursor:default; }
|
|
199
200
|
.desktop-queue svg,
|
|
200
201
|
:deep(.desktop-queue__action svg) { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round; }
|
|
202
|
+
.desktop-queue[data-tone="mobile"] { width:auto; margin:0 16px 8px; padding:0; }
|
|
203
|
+
.desktop-queue[data-tone="mobile"] .desktop-queue__panel { border-bottom:1px solid var(--q-separator); border-radius:14px; }
|
|
204
|
+
.desktop-queue[data-tone="mobile"] :deep(.desktop-queue__action) { width:36px; height:36px; }
|
|
201
205
|
</style>
|
|
@@ -130,13 +130,23 @@
|
|
|
130
130
|
@answer="forwardAnswer"
|
|
131
131
|
/>
|
|
132
132
|
<LaresDesktopQueue
|
|
133
|
+
tone="mobile"
|
|
133
134
|
:items="state.queue"
|
|
134
135
|
:running="state.running"
|
|
135
136
|
:busy="state.queueBusy"
|
|
136
137
|
:t="t"
|
|
137
138
|
@action="(itemId, action) => $emit('queue-action', itemId, action)"
|
|
138
139
|
/>
|
|
140
|
+
<div v-if="state.approval" class="lares-mobile-shell__approval">
|
|
141
|
+
<LaresApprovalCard
|
|
142
|
+
:approval="state.approval"
|
|
143
|
+
:busy="state.approvalBusy"
|
|
144
|
+
:t="t"
|
|
145
|
+
@answer="$emit('answer-approval', $event)"
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
139
148
|
<LaresComposer
|
|
149
|
+
v-else
|
|
140
150
|
ref="composer"
|
|
141
151
|
:draft="state.draft"
|
|
142
152
|
:sending="state.sending"
|
|
@@ -231,6 +241,7 @@
|
|
|
231
241
|
import LaresChatBar from "../chat/ChatBar.vue";
|
|
232
242
|
import LaresHistoryPanel from "../chat/HistoryPanel.vue";
|
|
233
243
|
import LaresTranscript from "../chat/Transcript.vue";
|
|
244
|
+
import LaresApprovalCard from "../chat/ApprovalCard.vue";
|
|
234
245
|
import LaresComposer from "../chat/Composer.vue";
|
|
235
246
|
import LaresDesktopQueue from "../desktop/DesktopQueue.vue";
|
|
236
247
|
import LaresPreview from "../preview/Preview.vue";
|
|
@@ -245,6 +256,7 @@ export default {
|
|
|
245
256
|
LaresChatBar,
|
|
246
257
|
LaresHistoryPanel,
|
|
247
258
|
LaresTranscript,
|
|
259
|
+
LaresApprovalCard,
|
|
248
260
|
LaresComposer,
|
|
249
261
|
LaresDesktopQueue,
|
|
250
262
|
LaresPreview,
|
|
@@ -266,7 +278,7 @@ export default {
|
|
|
266
278
|
},
|
|
267
279
|
emits: [
|
|
268
280
|
"history", "create", "toggle-speak", "close-history", "pick-session", "retry", "open-file",
|
|
269
|
-
"answer", "update-draft", "send", "queue-action", "open-model", "open-effort", "files",
|
|
281
|
+
"answer", "answer-approval", "update-draft", "send", "queue-action", "open-model", "open-effort", "files",
|
|
270
282
|
"voice", "voice-action", "hold-start", "hold-end", "close-model", "choose-model",
|
|
271
283
|
"close-effort", "choose-effort", "close-preview",
|
|
272
284
|
"open-commands", "open-references", "pick-command", "remove-image",
|
|
@@ -335,6 +347,11 @@ export default {
|
|
|
335
347
|
flex-direction: column;
|
|
336
348
|
}
|
|
337
349
|
|
|
350
|
+
.lares-mobile-shell__approval {
|
|
351
|
+
flex: none;
|
|
352
|
+
margin: 0 16px calc(12px + env(safe-area-inset-bottom, 0px));
|
|
353
|
+
}
|
|
354
|
+
|
|
338
355
|
.lares-shell__status,
|
|
339
356
|
.lares-shell__hint {
|
|
340
357
|
margin: 0 20px;
|