openvisio-agent 0.21.1 → 0.22.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 +11 -0
- package/README.md +5 -1
- package/USER_GUIDE.md +2 -2
- package/package.json +2 -2
- package/scenarios/runtime.scenarios.mjs +6 -11
- package/scenarios/workspace.scenarios.mjs +2 -1
- package/scripts/certify.mjs +11 -11
- package/src/codex-mcp-proxy.mjs +12 -1
- package/src/events.mjs +7 -1
- package/src/mastra-harness.mjs +19 -17
- package/src/memory.mjs +4 -3
- package/src/opencode-config.mjs +13 -16
- package/src/runtime-control.mjs +50 -0
- package/src/watch.mjs +153 -128
- package/studio/app.mjs +6 -5
- package/studio/guide.html +2 -1
package/studio/app.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The studio displays recorded, visible actions. It never starts work or infers a plan.
|
|
2
2
|
const MAX_EVENTS = 1000;
|
|
3
3
|
const PAGE_SIZE = 40;
|
|
4
|
-
const terminalStatuses = new Set(['completed', 'failed', 'cancelled', 'offline', 'skipped', 'blocked', 'timeout']);
|
|
4
|
+
const terminalStatuses = new Set(['completed', 'failed', 'cancelled', 'offline', 'skipped', 'blocked', 'timeout', 'continued']);
|
|
5
5
|
const text = (value, max = 24000) => value == null ? '' : String(value).slice(0, max);
|
|
6
6
|
const record = value => value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
7
7
|
const array = value => Array.isArray(value) ? value : [];
|
|
@@ -17,7 +17,7 @@ export function normalizeStatus(value, fallback = 'observed') {
|
|
|
17
17
|
if (['failed', 'failure', 'error', 'rejected', 'rate_limited'].includes(status)) return 'failed';
|
|
18
18
|
if (['cancelled', 'canceled', 'aborted', 'interrupted'].includes(status)) return 'cancelled';
|
|
19
19
|
if (['offline', 'stopped', 'disconnected', 'exited'].includes(status)) return 'offline';
|
|
20
|
-
if (['skipped', 'recovering', 'idle', 'blocked', 'timeout'].includes(status)) return status;
|
|
20
|
+
if (['skipped', 'recovering', 'idle', 'blocked', 'timeout', 'continued'].includes(status)) return status;
|
|
21
21
|
if (['starting', 'connecting', 'reused'].includes(status)) return 'connecting';
|
|
22
22
|
return fallback;
|
|
23
23
|
}
|
|
@@ -76,7 +76,7 @@ export function deriveModel(input) {
|
|
|
76
76
|
cycle.events.push(event);
|
|
77
77
|
cycle.lastSeen = event.timestamp;
|
|
78
78
|
// Merge only fields that describe the cycle; tool kind/status belong to that tool.
|
|
79
|
-
for (const field of ['model', 'workdir', 'watcherPid', 'ticket', 'thread', 'lane', 'queueMs', 'durationMs', 'reason']) {
|
|
79
|
+
for (const field of ['model', 'workdir', 'watcherPid', 'ticket', 'thread', 'lane', 'queueMs', 'durationMs', 'reason', 'finishedBy']) {
|
|
80
80
|
if (data[field] != null) cycle.data[field] = data[field];
|
|
81
81
|
}
|
|
82
82
|
if (event.type.startsWith('cycle.')) {
|
|
@@ -185,6 +185,7 @@ export function eventTitle(event) {
|
|
|
185
185
|
const titles = {
|
|
186
186
|
'runtime.started': 'Watcher connected', 'runtime.heartbeat': 'Watcher heartbeat', 'runtime.stopped': 'Watcher stopped',
|
|
187
187
|
'cycle.queued': 'Cycle queued', 'cycle.started': 'Cycle started', 'cycle.finished': 'Cycle finished',
|
|
188
|
+
'cycle.continued': 'Continued in coding workspace',
|
|
188
189
|
'cycle.completed': 'Cycle completed', 'cycle.cancelled': 'Cycle cancelled', 'cycle.failed': 'Cycle failed',
|
|
189
190
|
'plan.updated': 'Plan updated', 'output.progress': 'Progress update', 'output.final': 'Final response',
|
|
190
191
|
'process.started': 'Coding runtime starting', 'process.ready': 'Coding runtime ready', 'process.stopped': 'Coding runtime stopped',
|
|
@@ -238,7 +239,7 @@ export function filterModelItems(model, { view = 'activity', selectedAgent = 'al
|
|
|
238
239
|
&& (!query || searchableEvent(event).includes(query)));
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
const statusLabels = { active: 'Active', queued: 'Queued', completed: 'Completed', failed: 'Failed', cancelled: 'Cancelled', offline: 'Offline', observed: 'Recorded', demo: 'Simulated', uninstrumented: 'No activity yet', unknown: 'Unknown', skipped: 'Skipped', recovering: 'Recovering', idle: 'Idle', blocked: 'Blocked', timeout: 'Timed out', connecting: 'Connecting' };
|
|
242
|
+
const statusLabels = { continued: 'Continued in workspace', active: 'Active', queued: 'Queued', completed: 'Completed', failed: 'Failed', cancelled: 'Cancelled', offline: 'Offline', observed: 'Recorded', demo: 'Simulated', uninstrumented: 'No activity yet', unknown: 'Unknown', skipped: 'Skipped', recovering: 'Recovering', idle: 'Idle', blocked: 'Blocked', timeout: 'Timed out', connecting: 'Connecting' };
|
|
242
243
|
const kindIcons = { cycle: 'stack', tool: 'tool', plan: 'list', output: 'message', runtime: 'pulse', process: 'terminal' };
|
|
243
244
|
const shortTime = timestamp => timeValue(timestamp) ? new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }) : '—';
|
|
244
245
|
const fullTime = timestamp => timeValue(timestamp) ? new Date(timestamp).toLocaleString() : 'Not recorded';
|
|
@@ -677,7 +678,7 @@ function initializeStudio() {
|
|
|
677
678
|
const count = node('span', 'badge fanout-count');
|
|
678
679
|
const dots = node('span', 'agent-dots'); dots.setAttribute('aria-hidden', 'true');
|
|
679
680
|
displayed.forEach((_, index) => dots.append(node('span', `dot agent-color-${index}`)));
|
|
680
|
-
count.append(dots, node('span', '', `${related.filter(item => item.status === 'completed').length}/${related.length}
|
|
681
|
+
count.append(dots, node('span', '', `${related.filter(item => item.status === 'completed').length}/${related.length} turns ended`));
|
|
681
682
|
header.append(title, count);
|
|
682
683
|
const surface = node('div', 'fanout-surface oa-inset');
|
|
683
684
|
const task = node('div', 'fanout-task');
|
package/studio/guide.html
CHANGED
|
@@ -76,10 +76,11 @@
|
|
|
76
76
|
<dl>
|
|
77
77
|
<dt>Live</dt><dd>Your browser is connected to the local Studio server. Check each agent’s own status to see whether its watcher is connected.</dd>
|
|
78
78
|
<dt>Queued / Active</dt><dd>Work is waiting to start, or the current watcher has recorded it as running.</dd>
|
|
79
|
-
<dt>Completed</dt><dd>The selected action or
|
|
79
|
+
<dt>Completed</dt><dd>The selected action finished, or the agent ended its turn. Ending a turn does not automatically mark its ticket done. A completed tool is only one step; inspect the cycle’s final response and the ticket for the overall result.</dd>
|
|
80
80
|
<dt>Blocked / Failed / Timed out</dt><dd>Read the cycle’s Outcome and final response, then check the ticket or watcher log for the cause. Studio has no retry or approval button.</dd>
|
|
81
81
|
<dt>Cancelled / Skipped</dt><dd>The work was stopped or did not proceed. These are separate from successful completion.</dd>
|
|
82
82
|
<dt>Idle / Connecting / Recovering</dt><dd>A coding runtime is waiting, connecting, or attempting recovery. These describe the runtime’s last recorded state.</dd>
|
|
83
|
+
<dt>Continued in workspace</dt><dd>The agent requested its coding workspace and carried the same request and context into a work session. Follow that session for the final response.</dd>
|
|
83
84
|
<dt>Offline</dt><dd>The watcher stopped reporting, exited, or was replaced by a newer run. An unfinished cycle’s outcome is unknown; offline does not mean completed or failed.</dd>
|
|
84
85
|
<dt>Simulated</dt><dd>This record belongs to the demonstration. No real agent is working on it.</dd>
|
|
85
86
|
</dl>
|