openvisio-agent 0.3.5 → 0.3.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/package.json +1 -1
- package/src/watch.mjs +14 -21
package/package.json
CHANGED
package/src/watch.mjs
CHANGED
|
@@ -11,15 +11,13 @@ import { join, dirname } from 'node:path'
|
|
|
11
11
|
import { OV_DIR, readConfig, onPath, fail, ok, info, slugify, stripSlash, chmodSafe } from './lib.mjs'
|
|
12
12
|
import { connectAgentWs, assertWebSocket } from './ws.mjs'
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const CODE_FULL = 'Run one OpenVisio autonomy cycle. ' + AUTH_NOTE + ' Call get_marching_orders and poll_inbox. You have file + Bash tools and a git repo at your working directory FOR CODE WORK ONLY. For assigned tickets or mentions asking for real code work: FIRST "git checkout -B agent/work", make the changes with Read/Edit/Write, run tests if present, then "git add -A && git commit -m ...". NEVER git push, merge, or touch main. Then comment_ticket with a short summary + the branch name, and post a brief channel reply. Do NOT use Bash for anything other than git/tests/build — never to find credentials. If you truly cannot (missing repo/specs), say so in one message — never fabricate.'
|
|
22
|
-
const CODE_FAST = AUTH_NOTE + ' New chat activity in OpenVisio. If a specific mention is given above, post that reply FIRST with mcp__openvisio-team__post_message — do this before any Bash. Then poll_inbox and handle .followUps (thread replies you are part of, even without an @mention), AT MOST ONE reply per channel. Only if a message asks for real CODE work in your git repo, do it on a branch (checkout -B agent/work, edit, commit locally — never push/merge) and reply with the branch name. Bash is for git/tests ONLY, never for credentials. 1-3 sentences, no summary. Then stop.'
|
|
14
|
+
// Behaviour prompts. The openvisio-team MCP bridge requires the agent's
|
|
15
|
+
// credentials as ARGUMENTS on every tool call — those are injected at runtime by
|
|
16
|
+
// loopBackendWs (see credNote), NOT baked in here, so nothing needs hunting.
|
|
17
|
+
const CYCLE = 'Run one OpenVisio autonomy cycle.'
|
|
18
|
+
const CYCLE_FAST = 'New chat activity in OpenVisio. If a specific mention is given above, post that reply FIRST with mcp__openvisio-team__post_message. Then call poll_inbox and handle any .followUps (thread replies you are part of, even without an @mention) — ignore .tasks/.claimable. Post AT MOST ONE reply per channel: if the same person sent several nudges, answer them together in ONE post. HONESTY: your only tools are the openvisio-team chat/ticket tools — you cannot write code or touch other tools; if asked for work you have no tool for, say so plainly in one short message (or offer to file a ticket). Never invent progress. Reply in 1-3 sentences, no summary. Then stop.'
|
|
19
|
+
const CODE_FULL = 'Run one OpenVisio autonomy cycle. Call get_marching_orders and poll_inbox. You have file + Bash tools and a git repo at your working directory FOR CODE WORK ONLY. For assigned tickets or mentions asking for real code work: FIRST "git checkout -B agent/work", make the changes with Read/Edit/Write, run tests if present, then "git add -A && git commit -m ...". NEVER git push, merge, or touch main. Then comment_ticket with a short summary + the branch name, and post a brief channel reply. Do NOT use Bash to find credentials — they are given to you. If you truly cannot (missing repo/specs), say so in one message — never fabricate.'
|
|
20
|
+
const CODE_FAST = 'New chat activity in OpenVisio. If a specific mention is given above, post that reply FIRST with mcp__openvisio-team__post_message — do this before any Bash. Then poll_inbox and handle .followUps (thread replies you are part of, even without an @mention), AT MOST ONE reply per channel. Only if a message asks for real CODE work in your git repo, do it on a branch (checkout -B agent/work, edit, commit locally — never push/merge) and reply with the branch name. Bash is for git/tests ONLY, never for credentials. 1-3 sentences, no summary. Then stop.'
|
|
23
21
|
|
|
24
22
|
const CODE_TOOLS = ['Read', 'Grep', 'Glob', 'Edit', 'Write', 'MultiEdit', 'TodoWrite', 'Bash', 'mcp__openvisio-team__*']
|
|
25
23
|
const DENY_TOOLS = ['Bash(git push:*)', 'Bash(git reset --hard:*)', 'Bash(git clean:*)', 'Bash(rm:*)', 'Bash(sudo:*)', 'Bash(chmod:*)', 'Bash(curl:*)', 'Bash(wget:*)', 'Bash(npm publish:*)', 'Bash(pnpm publish:*)', 'Bash(gh pr merge:*)', 'Bash(gh repo:*)']
|
|
@@ -167,13 +165,10 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
167
165
|
// events and drained into the next cycle's prompt.
|
|
168
166
|
const pending = []
|
|
169
167
|
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const pulseTyping = () => { if (typingChan != null && handle) handle.sendTyping(typingChan) }
|
|
175
|
-
const startTyping = (cid) => { if (cid == null) return; typingChan = cid; pulseTyping(); if (!typingTimer) typingTimer = setInterval(pulseTyping, 3000) }
|
|
176
|
-
const stopTyping = () => { typingChan = null; if (typingTimer) { clearInterval(typingTimer); typingTimer = null } }
|
|
168
|
+
// The Mastra bridge authenticates per-CALL, not per-connection: every
|
|
169
|
+
// openvisio-team tool needs agent_identifier + agent_api_key as arguments.
|
|
170
|
+
// Hand them to the model up front so it never shells around hunting for them.
|
|
171
|
+
const credNote = `AUTH: the openvisio-team (mcp__openvisio-team__*) tools REQUIRE two arguments on EVERY call — agent_identifier: "${identifier}" and agent_api_key: "${apiKey}". Include BOTH on every openvisio-team tool call (post_message, poll_inbox, react_message, comment_ticket, …). They are given to you right here: do NOT search for them, do NOT run Bash/shell/grep/cat/find, do NOT read memory — just call the tools with these exact values.`
|
|
177
172
|
|
|
178
173
|
async function drain(kind, context) {
|
|
179
174
|
if (context) pending.push(context)
|
|
@@ -181,14 +176,13 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
181
176
|
busy = true
|
|
182
177
|
const ctx = pending.splice(0) // take everything accumulated so far
|
|
183
178
|
const base = kind === 'full' ? fullPrompt : fastPrompt
|
|
184
|
-
const prompt = ctx.length ? ctx.join('\n') + '\n\n'
|
|
179
|
+
const prompt = credNote + '\n\n' + (ctx.length ? ctx.join('\n') + '\n\n' : '') + base
|
|
185
180
|
log('running ' + kind + ' cycle…' + (ctx.length ? ' (' + ctx.length + ' event' + (ctx.length === 1 ? '' : 's') + ')' : ''))
|
|
186
181
|
try {
|
|
187
182
|
await runCycle(prompt)
|
|
188
183
|
} finally {
|
|
189
184
|
busy = false
|
|
190
185
|
if (queued || pending.length) { const next = queued || 'fast'; queued = null; void drain(next) }
|
|
191
|
-
else stopTyping()
|
|
192
186
|
}
|
|
193
187
|
}
|
|
194
188
|
|
|
@@ -214,9 +208,8 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
214
208
|
const text = String(msg.content || msg.body || msg.text || '').replace(/\s+/g, ' ').slice(0, 600)
|
|
215
209
|
const who = senderName(msg)
|
|
216
210
|
log('agent:mention in channel ' + (cid != null ? cid : '?'))
|
|
217
|
-
startTyping(cid) // show the agent as typing immediately, before the cycle finishes
|
|
218
211
|
const ctx = cid != null
|
|
219
|
-
? `You were @mentioned in OpenVisio channel ${cid}${who ? ` by ${who}` : ''}: "${text}". Your FIRST action must be mcp__openvisio-team__post_message with channel_id ${cid}
|
|
212
|
+
? `You were @mentioned in OpenVisio channel ${cid}${who ? ` by ${who}` : ''}: "${text}". Your FIRST action must be mcp__openvisio-team__post_message with channel_id ${cid}, a 1-3 sentence reply, and the agent_identifier + agent_api_key from the AUTH line above. You already have the message here — do NOT poll_inbox to find it. After posting, you MAY poll_inbox once for other .followUps.`
|
|
220
213
|
: undefined
|
|
221
214
|
void drain('fast', ctx)
|
|
222
215
|
} else {
|
|
@@ -241,7 +234,7 @@ function loopBackendWs({ wsUrl, apiKey, identifier, claude, mcpConfig, workdir,
|
|
|
241
234
|
return new Promise(() => {
|
|
242
235
|
// Run until killed. Tidy up the socket on termination so a restarting
|
|
243
236
|
// service doesn't leak a half-open connection.
|
|
244
|
-
const bye = () => { clearInterval(sweep);
|
|
237
|
+
const bye = () => { clearInterval(sweep); try { handle && handle.close() } catch { /* noop */ } process.exit(0) }
|
|
245
238
|
process.on('SIGTERM', bye)
|
|
246
239
|
process.on('SIGINT', bye)
|
|
247
240
|
})
|