@7n/tauri-components 0.13.4 → 0.13.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.6] - 2026-07-20
4
+
5
+ ### Changed
6
+
7
+ - AgentDialog: перемикання агента mid-conversation тепер зберігає видимий чат-лог і передає новому агенту текстовий дайджест попередньої розмови як контекст, замість повного скидання
8
+
9
+ ## [0.13.5] - 2026-07-20
10
+
11
+ ### Fixed
12
+
13
+ - acp-kit: помилка невдалого запиту (error) тепер повертається в UI-конверт, а не лише пишеться в journal — RequestView більше не показує порожній 'failed' без пояснення
14
+
3
15
  ## [0.13.4] - 2026-07-20
4
16
 
5
17
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@7n/tauri-components",
3
- "version": "0.13.4",
3
+ "version": "0.13.6",
4
4
  "type": "module",
5
5
  "description": "Shared LLM agent engine + Vue/Quasar UI for Tauri apps (chat, journal, trust-tier approval).",
6
6
  "license": "MIT",
@@ -30,6 +30,7 @@
30
30
  <div v-if="turns.length" ref="logEl" class="chat-log">
31
31
  <template v-for="(turn, i) in turns" :key="i">
32
32
  <div v-if="turn.role === 'user'" class="chat-user">{{ turn.text }}</div>
33
+ <div v-else-if="turn.role === 'switch'" class="chat-switch">→ {{ turn.label }}</div>
33
34
  <template v-else>
34
35
  <div class="chat-model-label">{{ turn.agentLabel }}</div>
35
36
  <RequestView :result="turn.result" />
@@ -151,18 +152,40 @@ function apply(outcome) {
151
152
  scrollToEnd()
152
153
  }
153
154
 
155
+ /**
156
+ * Render the transcript so far as plain text, for handing off to a freshly
157
+ * spawned agent that's replacing whichever one the conversation started
158
+ * with — a new ACP session has no memory of it otherwise.
159
+ * @returns {string} context block, or '' when there's nothing to hand off
160
+ */
161
+ function handoffContext() {
162
+ const relevant = turns.value.filter(turn => turn.role !== 'switch')
163
+ if (!relevant.length) return ''
164
+ const lines = relevant.map(turn =>
165
+ turn.role === 'user'
166
+ ? `Користувач: ${turn.text}`
167
+ : `Агент (${turn.agentLabel}): ${turn.result?.summary ?? turn.result?.question ?? ''}`
168
+ )
169
+ return `Контекст попередньої розмови (продовжуєш замість іншого агента):\n${lines.join('\n')}\n\nНове повідомлення:\n`
170
+ }
171
+
154
172
  /**
155
173
  * Send the current message: start a new request, or resume the conversation
156
174
  * — unless the agent/tier dropdowns have moved away from whichever agent
157
- * spawned the active session, in which case restart as a fresh conversation
175
+ * spawned the active session, in which case restart as a fresh ACP session
158
176
  * (equivalent to closing and reopening the dialog) so the new message
159
- * actually goes to the newly selected agent.
177
+ * actually goes to the newly selected agent. The visible transcript keeps
178
+ * growing across the switch, and the prior turns are prepended as plain-text
179
+ * context to the new agent's first message so it can actually continue the
180
+ * conversation rather than starting blind.
160
181
  */
161
182
  async function send() {
162
183
  const text = prompt.value.trim()
163
184
  if (!text || running.value) return
164
- if (requestId.value && currentSpawnKey() !== activeSpawnKey.value) {
165
- turns.value = []
185
+ const switching = Boolean(requestId.value) && currentSpawnKey() !== activeSpawnKey.value
186
+ const payload = switching ? `${handoffContext()}${text}` : text
187
+ if (switching) {
188
+ turns.value.push({ role: 'switch', label: currentAgentLabel() })
166
189
  requestId.value = null
167
190
  }
168
191
  prompt.value = ''
@@ -177,7 +200,7 @@ async function send() {
177
200
  activeAgentLabel.value = currentAgentLabel()
178
201
  activeSpawnKey.value = currentSpawnKey()
179
202
  }
180
- apply(await (requestId.value ? respond(requestId.value, text) : request(text)))
203
+ apply(await (requestId.value ? respond(requestId.value, payload) : request(payload)))
181
204
  } catch (error) {
182
205
  $q.notify({ type: 'negative', message: String(error?.message ?? error) })
183
206
  } finally {
@@ -217,6 +240,14 @@ async function send() {
217
240
  margin-bottom: -4px;
218
241
  }
219
242
 
243
+ .chat-switch {
244
+ align-self: center;
245
+ font-size: 11px;
246
+ opacity: 0.55;
247
+ text-transform: uppercase;
248
+ letter-spacing: 0.02em;
249
+ }
250
+
220
251
  .chat-thinking {
221
252
  display: flex;
222
253
  align-items: center;
@@ -3,7 +3,7 @@ type: Vue Component
3
3
  title: AgentDialog.vue
4
4
  resource: npm/src/components/AgentDialog.vue
5
5
  docgen:
6
- crc: 0c46e2c2
6
+ crc: b4a8b043
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  ---
9
9
 
@@ -141,8 +141,17 @@ export function createAcpAgentKit({
141
141
  try {
142
142
  turn = await turnPromise
143
143
  } catch (error) {
144
- await journal.update(requestId, { status: 'failed', error: String(error?.message ?? error) })
145
- return { requestId, status: 'failed', summary: null, actions: baseActions, question: null, pendingApproval: null }
144
+ const message = String(error?.message ?? error)
145
+ await journal.update(requestId, { status: 'failed', error: message })
146
+ return {
147
+ requestId,
148
+ status: 'failed',
149
+ summary: null,
150
+ error: message,
151
+ actions: baseActions,
152
+ question: null,
153
+ pendingApproval: null
154
+ }
146
155
  }
147
156
  const fields = finalizeTurn(turn)
148
157
  const actions = [...baseActions, ...turn.trace]
@@ -3,7 +3,7 @@ type: JS Module
3
3
  title: acp-kit.js
4
4
  resource: npm/src/core/acp-kit.js
5
5
  docgen:
6
- crc: 7838ed4e
6
+ crc: f5342002
7
7
  model: omlx/gemma-4-e4b-it-OptiQ-4bit
8
8
  score: 100
9
9
  judgeModel: openai-codex/gpt-5.4-mini