@7n/tauri-components 0.13.11 → 0.14.0
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 +6 -0
- package/package.json +1 -1
- package/src/components/AgentDialog.vue +28 -10
- package/src/components/AuditDialog.vue +5 -1
- package/src/components/docs/AgentDialog.md +1 -1
- package/src/components/docs/AuditDialog.md +1 -1
- package/src/core/acp-agent.js +2 -2
- package/src/core/acp-kit.js +6 -6
- package/src/core/docs/acp-agent.md +1 -1
- package/src/core/docs/acp-kit.md +1 -1
- package/src/core/scope.js +1 -1
- package/src/vue/docs/use-acp-agent.md +1 -1
- package/src/vue/use-acp-agent.js +9 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.14.0] - 2026-07-21
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- AgentDialog: інкрементальний стрімінг відповіді (текст/tool-call з'являються по мірі надходження session/update-чанків, а не лише після завершення всього ходу). AuditDialog: коректно показує нативні ACP permission-request поряд з MCP tool-call approval в одному списку.
|
|
8
|
+
|
|
3
9
|
## [0.13.11] - 2026-07-21
|
|
4
10
|
|
|
5
11
|
### Changed
|
package/package.json
CHANGED
|
@@ -142,12 +142,14 @@ async function scrollToEnd() {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
*
|
|
145
|
+
* Fill in the live turn with the final result, latch the conversation id,
|
|
146
|
+
* refresh the graph on writes.
|
|
146
147
|
* @param {object} outcome structured result from request/respond
|
|
148
|
+
* @param {object} turn the live turn pushed at the start of send(), updated in place
|
|
147
149
|
*/
|
|
148
|
-
function apply(outcome) {
|
|
150
|
+
function apply(outcome, turn) {
|
|
149
151
|
if (outcome.requestId) requestId.value = outcome.requestId
|
|
150
|
-
|
|
152
|
+
turn.result = outcome
|
|
151
153
|
if (outcome.actions?.some(action => action.envelope?.ok)) emit('ran')
|
|
152
154
|
scrollToEnd()
|
|
153
155
|
}
|
|
@@ -202,17 +204,33 @@ async function send() {
|
|
|
202
204
|
}
|
|
203
205
|
prompt.value = ''
|
|
204
206
|
turns.value.push({ role: 'user', text })
|
|
207
|
+
// Only a fresh request() actually spawns with the currently-selected
|
|
208
|
+
// agent/tier — a respond() keeps talking to whatever the conversation
|
|
209
|
+
// already started with, so the label must not move mid-conversation.
|
|
210
|
+
if (!requestId.value) {
|
|
211
|
+
activeAgentLabel.value = currentAgentLabel()
|
|
212
|
+
activeSpawnKey.value = currentSpawnKey()
|
|
213
|
+
}
|
|
214
|
+
// Pushed before the call resolves and updated in place as session/update
|
|
215
|
+
// chunks stream in (onChunk below), so the reply grows live instead of
|
|
216
|
+
// only appearing once the whole turn finishes.
|
|
217
|
+
const liveTurn = {
|
|
218
|
+
role: 'agent',
|
|
219
|
+
agentLabel: activeAgentLabel.value,
|
|
220
|
+
result: { status: 'running', summary: '', actions: [], question: null, pendingApproval: null }
|
|
221
|
+
}
|
|
222
|
+
turns.value.push(liveTurn)
|
|
205
223
|
scrollToEnd()
|
|
206
224
|
running.value = true
|
|
207
225
|
try {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (!requestId.value) {
|
|
212
|
-
activeAgentLabel.value = currentAgentLabel()
|
|
213
|
-
activeSpawnKey.value = currentSpawnKey()
|
|
226
|
+
const onChunk = ({ text: liveText, actions }) => {
|
|
227
|
+
liveTurn.result = { ...liveTurn.result, summary: liveText, actions }
|
|
228
|
+
scrollToEnd()
|
|
214
229
|
}
|
|
215
|
-
|
|
230
|
+
const outcome = await (requestId.value
|
|
231
|
+
? respond(requestId.value, payload, { onChunk })
|
|
232
|
+
: request(payload, { onChunk }))
|
|
233
|
+
apply(outcome, liveTurn)
|
|
216
234
|
} catch (error) {
|
|
217
235
|
$q.notify({ type: 'negative', message: String(error?.message ?? error) })
|
|
218
236
|
} finally {
|
|
@@ -25,7 +25,11 @@
|
|
|
25
25
|
<div v-if="expandedId === rec.id" class="audit-body">
|
|
26
26
|
<RequestView @respond="msg => onRespond(rec, msg)" :result="rec" :busy="busyId === rec.id" />
|
|
27
27
|
<div v-if="rec.status === 'needs_approval' && rec.pendingApproval" class="audit-approval">
|
|
28
|
-
<div class="audit-pending">
|
|
28
|
+
<div v-if="rec.pendingApproval.kind === 'acp'" class="audit-pending">
|
|
29
|
+
Permission request:
|
|
30
|
+
<code>{{ rec.pendingApproval.toolCall?.title ?? rec.pendingApproval.toolCall?.toolCallId }}</code>
|
|
31
|
+
</div>
|
|
32
|
+
<div v-else class="audit-pending">
|
|
29
33
|
Approve action: <code>{{ rec.pendingApproval.tool }}({{ JSON.stringify(rec.pendingApproval.input) }})</code>
|
|
30
34
|
</div>
|
|
31
35
|
<div class="row q-gutter-sm">
|
package/src/core/acp-agent.js
CHANGED
|
@@ -101,7 +101,7 @@ function applySessionUpdate(state, update) {
|
|
|
101
101
|
* @param {object} params turn parameters
|
|
102
102
|
* @param {string} params.sessionKey handle from `createAcpSession`
|
|
103
103
|
* @param {string} params.text prompt text for this turn
|
|
104
|
-
* @param {(
|
|
104
|
+
* @param {(snapshot: {text: string, actions: {tool: string, input: object, envelope: object|null}[]}) => void} [params.onChunk] optional live callback with the turn's accumulated text/tool-calls so far, fired on every session/update (UI streaming)
|
|
105
105
|
* @returns {Promise<{content: string, steps: number, trace: object[], messages: object[], stopped?: string}>} runAgent()-shaped result
|
|
106
106
|
*/
|
|
107
107
|
export async function runAcpTurn({ sessionKey, text, onChunk }) {
|
|
@@ -110,7 +110,7 @@ export async function runAcpTurn({ sessionKey, text, onChunk }) {
|
|
|
110
110
|
const unlisten = await listen('acp://session-update', event => {
|
|
111
111
|
if (event.payload?.sessionKey !== sessionKey) return
|
|
112
112
|
applySessionUpdate(state, event.payload.update)
|
|
113
|
-
onChunk?.(
|
|
113
|
+
onChunk?.({ text: state.text, actions: state.calls.values().toArray() })
|
|
114
114
|
})
|
|
115
115
|
|
|
116
116
|
try {
|
package/src/core/acp-kit.js
CHANGED
|
@@ -175,10 +175,10 @@ export function createAcpAgentKit({
|
|
|
175
175
|
/**
|
|
176
176
|
* Start a new ACP-backed request: spawns the agent session and runs the
|
|
177
177
|
* first prompt turn.
|
|
178
|
-
* @param {{intent: string, agent: object}} opts `agent` is passed straight to `createAcpSession` (agentKind/command/args/env/cwd/…)
|
|
178
|
+
* @param {{intent: string, agent: object, onChunk?: (snapshot: {text: string, actions: object[]}) => void}} opts `agent` is passed straight to `createAcpSession` (agentKind/command/args/env/cwd/…); `onChunk` streams live text/tool-calls as the turn runs
|
|
179
179
|
* @returns {Promise<object>} structured result envelope
|
|
180
180
|
*/
|
|
181
|
-
async request({ intent, agent }) {
|
|
181
|
+
async request({ intent, agent, onChunk }) {
|
|
182
182
|
await ensureListening()
|
|
183
183
|
const id = await journal.create({ intent, actor: AGENT_ACTOR })
|
|
184
184
|
await journal.update(id, { status: 'running' })
|
|
@@ -191,15 +191,15 @@ export function createAcpAgentKit({
|
|
|
191
191
|
activeSessionKey = session.sessionKey
|
|
192
192
|
activeRequestId = id
|
|
193
193
|
await journal.update(id, { acp: { agentKind: session.agentKind, sessionKey: session.sessionKey } })
|
|
194
|
-
return runAndJournal(id, [], deps.runAcpTurn({ sessionKey: activeSessionKey, text: intent }))
|
|
194
|
+
return runAndJournal(id, [], deps.runAcpTurn({ sessionKey: activeSessionKey, text: intent, onChunk }))
|
|
195
195
|
},
|
|
196
196
|
|
|
197
197
|
/**
|
|
198
198
|
* Continue the active session with a follow-up message.
|
|
199
|
-
* @param {{requestId: string, message: string}} opts resume parameters
|
|
199
|
+
* @param {{requestId: string, message: string, onChunk?: (snapshot: {text: string, actions: object[]}) => void}} opts resume parameters; `onChunk` streams live text/tool-calls as the turn runs
|
|
200
200
|
* @returns {Promise<object>} updated result envelope
|
|
201
201
|
*/
|
|
202
|
-
async respond({ requestId, message }) {
|
|
202
|
+
async respond({ requestId, message, onChunk }) {
|
|
203
203
|
if (!activeSessionKey) {
|
|
204
204
|
return {
|
|
205
205
|
requestId,
|
|
@@ -228,7 +228,7 @@ export function createAcpAgentKit({
|
|
|
228
228
|
return runAndJournal(
|
|
229
229
|
requestId,
|
|
230
230
|
record.actions ?? [],
|
|
231
|
-
deps.runAcpTurn({ sessionKey: activeSessionKey, text: message })
|
|
231
|
+
deps.runAcpTurn({ sessionKey: activeSessionKey, text: message, onChunk })
|
|
232
232
|
)
|
|
233
233
|
},
|
|
234
234
|
|
package/src/core/docs/acp-kit.md
CHANGED
package/src/core/scope.js
CHANGED
|
@@ -22,7 +22,7 @@ export function classify(catalog, actorTiers, actor, toolName) {
|
|
|
22
22
|
const tiers = actorTiers ?? DEFAULT_ACTOR_TIERS
|
|
23
23
|
const tool = getTool(catalog, toolName)
|
|
24
24
|
if (!tool) return 'deny'
|
|
25
|
-
const rank = TIER_RANK[tool.tier] ??
|
|
25
|
+
const rank = TIER_RANK[tool.tier] ?? Infinity
|
|
26
26
|
const max = tiers[actor?.kind] ?? 0
|
|
27
27
|
if (rank <= max) return 'allow'
|
|
28
28
|
if (tool.tier === 'destructive' && actor?.kind === 'agent') return 'approval'
|
package/src/vue/use-acp-agent.js
CHANGED
|
@@ -114,14 +114,20 @@ export function useAcpAgent({
|
|
|
114
114
|
journal,
|
|
115
115
|
/**
|
|
116
116
|
* @param {string} intent user prompt
|
|
117
|
-
* @param {{modelTier?: string}} [opts] per-call overrides
|
|
117
|
+
* @param {{modelTier?: string, onChunk?: (snapshot: {text: string, actions: object[]}) => void}} [opts] per-call overrides; `onChunk` streams live text/tool-calls as the turn runs
|
|
118
118
|
* @returns {Promise<object>} structured result envelope
|
|
119
119
|
*/
|
|
120
120
|
request: (intent, opts = {}) => {
|
|
121
121
|
if (opts.modelTier) modelTier.value = opts.modelTier
|
|
122
|
-
return kit.request({ intent, agent: resolveSpawnArgs() })
|
|
122
|
+
return kit.request({ intent, agent: resolveSpawnArgs(), onChunk: opts.onChunk })
|
|
123
123
|
},
|
|
124
|
-
|
|
124
|
+
/**
|
|
125
|
+
* @param {string} requestId journal record id from a prior request()/respond()
|
|
126
|
+
* @param {string} message follow-up user message
|
|
127
|
+
* @param {{onChunk?: (snapshot: {text: string, actions: object[]}) => void}} [opts] `onChunk` streams live text/tool-calls as the turn runs
|
|
128
|
+
* @returns {Promise<object>} updated result envelope
|
|
129
|
+
*/
|
|
130
|
+
respond: (requestId, message, opts = {}) => kit.respond({ requestId, message, onChunk: opts.onChunk }),
|
|
125
131
|
approve: (requestId, approve) => kit.approve({ requestId, approve })
|
|
126
132
|
}
|
|
127
133
|
}
|