openvisio-agent 0.3.6 → 0.3.7
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 +1 -1
- package/src/watch.mjs +16 -16
package/package.json
CHANGED
package/src/watch.mjs
CHANGED
|
@@ -158,7 +158,6 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
158
158
|
let busy = false
|
|
159
159
|
let queued = null // 'full' | 'fast' — a cycle requested while one was running
|
|
160
160
|
let handle = null
|
|
161
|
-
let lastActivityAt = Date.now()
|
|
162
161
|
// Context lines from the events themselves (the WS payload already carries the
|
|
163
162
|
// channel + message / task), so the agent acts on THEM directly instead of
|
|
164
163
|
// hoping poll_inbox re-surfaces the same item. Accumulated across coalesced
|
|
@@ -196,7 +195,6 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
196
195
|
|
|
197
196
|
function onEvent(k, d) {
|
|
198
197
|
const raw = d && typeof d === 'object' ? d : {}
|
|
199
|
-
lastActivityAt = Date.now()
|
|
200
198
|
if (k === 'task:assigned') {
|
|
201
199
|
const t = raw.task || {}
|
|
202
200
|
log('task:assigned ' + (t.id != null ? '#' + t.id + ' “' + (t.title || '') + '”' : ''))
|
|
@@ -207,34 +205,36 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
207
205
|
const msg = raw.message && typeof raw.message === 'object' ? raw.message : {}
|
|
208
206
|
const text = String(msg.content || msg.body || msg.text || '').replace(/\s+/g, ' ').slice(0, 600)
|
|
209
207
|
const who = senderName(msg)
|
|
210
|
-
|
|
208
|
+
// Reply IN THE SAME THREAD: parent is the thread root (the message's own id
|
|
209
|
+
// for a top-level mention, or its parent when the mention is itself a reply).
|
|
210
|
+
const mid = msg.id != null ? msg.id : (msg.message_id != null ? msg.message_id : null)
|
|
211
|
+
const parent = msg.parent_id != null ? msg.parent_id : (msg.parentId != null ? msg.parentId : null)
|
|
212
|
+
const threadRoot = parent != null ? parent : mid
|
|
213
|
+
log('agent:mention in channel ' + (cid != null ? cid : '?') + (threadRoot != null ? ' (thread ' + threadRoot + ')' : ''))
|
|
211
214
|
const ctx = cid != null
|
|
212
|
-
? `You were @mentioned in OpenVisio channel ${cid}${who ? ` by ${who}` : ''}: "${text}".
|
|
215
|
+
? `You were @mentioned in OpenVisio channel ${cid}${who ? ` by "${who}"` : ''}: "${text}". Reply with mcp__openvisio-team__post_message as your FIRST action — arguments: channel_id ${cid}${threadRoot != null ? `, parent_id ${threadRoot} (reply IN THAT THREAD, do not start a new top-level message)` : ''}, plus agent_identifier + agent_api_key from the AUTH line above, and a 1-3 sentence reply.${who ? ` To @mention them back, write their EXACT full name "@${who}" (a mention only links when the name matches exactly — "@${who.split(' ')[0]}" alone will NOT).` : ''} You already have the message here — do NOT poll_inbox to find it.`
|
|
213
216
|
: undefined
|
|
214
217
|
void drain('fast', ctx)
|
|
218
|
+
} else if (k === 'error') {
|
|
219
|
+
// Surface the backend's rejection detail instead of a bare "event error".
|
|
220
|
+
log('error event: ' + JSON.stringify(raw).slice(0, 220))
|
|
215
221
|
} else {
|
|
216
222
|
log('event ' + k)
|
|
217
223
|
}
|
|
218
224
|
}
|
|
219
225
|
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const sweep = setInterval(() => {
|
|
226
|
-
if (busy) return
|
|
227
|
-
if (Date.now() - lastActivityAt > ACTIVE_WINDOW_MS) return // idle → don't spend a cycle
|
|
228
|
-
void drain('fast', 'Follow-up check: call poll_inbox and reply to any NEW .followUps (thread replies you are part of, even with no @mention) or unanswered .mentions. If there is nothing new, do nothing and stop — do NOT post.')
|
|
229
|
-
}, FOLLOWUP_MS)
|
|
230
|
-
|
|
226
|
+
// NO polling — the WebSocket is the only trigger (task:assigned / agent:mention).
|
|
227
|
+
// A thread reply that @mentions the agent fires agent:mention and is handled
|
|
228
|
+
// in-thread above; genuinely un-mentioned thread activity has no WS event, so
|
|
229
|
+
// it's a backend concern (dispatch a thread event to participant agents), not a
|
|
230
|
+
// reason to poll.
|
|
231
231
|
log('up — backend WS watcher on ' + wsUrl + (canCode ? ' [code: ' + workdir + ']' : ''))
|
|
232
232
|
handle = connectAgentWs({ wsUrl, apiKey, identifier, onEvent, log })
|
|
233
233
|
|
|
234
234
|
return new Promise(() => {
|
|
235
235
|
// Run until killed. Tidy up the socket on termination so a restarting
|
|
236
236
|
// service doesn't leak a half-open connection.
|
|
237
|
-
const bye = () => {
|
|
237
|
+
const bye = () => { try { handle && handle.close() } catch { /* noop */ } process.exit(0) }
|
|
238
238
|
process.on('SIGTERM', bye)
|
|
239
239
|
process.on('SIGINT', bye)
|
|
240
240
|
})
|