@openscout/scout 0.2.48 → 0.2.49
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/README.md +1 -1
- package/dist/control-plane-client/assets/{arc.es-DndjiskC.js → arc.es-CcKhIPRw.js} +1 -1
- package/dist/control-plane-client/assets/index-BGcMYoYJ.css +1 -0
- package/dist/control-plane-client/assets/index-BkEXBsPk.js +140 -0
- package/dist/control-plane-client/index.html +2 -2
- package/dist/main.mjs +36732 -20558
- package/dist/pair-supervisor.mjs +42 -17
- package/dist/scout-control-plane-web.mjs +39 -5
- package/dist/scout-web-server.mjs +13 -3
- package/package.json +2 -2
- package/dist/control-plane-client/assets/index-CCQvN8TG.css +0 -1
- package/dist/control-plane-client/assets/index-DlKOe-t6.js +0 -140
package/dist/pair-supervisor.mjs
CHANGED
|
@@ -14109,12 +14109,38 @@ function compact(p) {
|
|
|
14109
14109
|
return null;
|
|
14110
14110
|
return p.startsWith(HOME) ? `~${p.slice(HOME.length)}` : p;
|
|
14111
14111
|
}
|
|
14112
|
+
var LATEST_AGENT_ENDPOINT_JOIN = `LEFT JOIN agent_endpoints ep ON ep.id = (
|
|
14113
|
+
SELECT ep2.id
|
|
14114
|
+
FROM agent_endpoints ep2
|
|
14115
|
+
WHERE ep2.agent_id = a.id
|
|
14116
|
+
ORDER BY ep2.updated_at DESC
|
|
14117
|
+
LIMIT 1
|
|
14118
|
+
)`;
|
|
14119
|
+
function queryExecutingAgentIds() {
|
|
14120
|
+
return new Set(db().prepare(`SELECT DISTINCT target_agent_id FROM flights
|
|
14121
|
+
WHERE state = 'running'`).all().map((row) => row.target_agent_id));
|
|
14122
|
+
}
|
|
14123
|
+
function summarizeAgentState(rawState, isWorking) {
|
|
14124
|
+
if (isWorking) {
|
|
14125
|
+
return "working";
|
|
14126
|
+
}
|
|
14127
|
+
return rawState && rawState !== "offline" ? "available" : "offline";
|
|
14128
|
+
}
|
|
14129
|
+
function summarizeAgentStatusLabel(rawState, isWorking) {
|
|
14130
|
+
switch (summarizeAgentState(rawState, isWorking)) {
|
|
14131
|
+
case "working":
|
|
14132
|
+
return "Working";
|
|
14133
|
+
case "available":
|
|
14134
|
+
return "Available";
|
|
14135
|
+
default:
|
|
14136
|
+
return "Offline";
|
|
14137
|
+
}
|
|
14138
|
+
}
|
|
14112
14139
|
function conversationIdForAgent(agentId) {
|
|
14113
14140
|
return `dm.operator.${agentId}`;
|
|
14114
14141
|
}
|
|
14115
14142
|
function queryMobileAgents(limit = 50) {
|
|
14116
|
-
const
|
|
14117
|
-
WHERE state NOT IN ('completed','failed','cancelled')`).all().map((r) => r.target_agent_id));
|
|
14143
|
+
const executingAgentIds = queryExecutingAgentIds();
|
|
14118
14144
|
const lastMessageAt = new Map(db().prepare(`SELECT actor_id, MAX(created_at) AS last_at FROM messages GROUP BY actor_id`).all().map((r) => [r.actor_id, r.last_at]));
|
|
14119
14145
|
const rows = db().prepare(`SELECT
|
|
14120
14146
|
a.id,
|
|
@@ -14129,17 +14155,17 @@ function queryMobileAgents(limit = 50) {
|
|
|
14129
14155
|
ep.updated_at
|
|
14130
14156
|
FROM agents a
|
|
14131
14157
|
JOIN actors ac ON ac.id = a.id
|
|
14132
|
-
|
|
14133
|
-
ORDER BY ep.updated_at DESC
|
|
14158
|
+
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
14159
|
+
ORDER BY COALESCE(ep.updated_at, 0) DESC, ac.display_name ASC
|
|
14134
14160
|
LIMIT ?`).all(limit);
|
|
14135
14161
|
return rows.map((r) => {
|
|
14136
14162
|
let meta = {};
|
|
14137
14163
|
try {
|
|
14138
14164
|
meta = r.metadata_json ? JSON.parse(r.metadata_json) : {};
|
|
14139
14165
|
} catch {}
|
|
14140
|
-
const isWorking =
|
|
14141
|
-
const state =
|
|
14142
|
-
const statusLabel =
|
|
14166
|
+
const isWorking = executingAgentIds.has(r.id);
|
|
14167
|
+
const state = summarizeAgentState(r.state, isWorking);
|
|
14168
|
+
const statusLabel = summarizeAgentStatusLabel(r.state, isWorking);
|
|
14143
14169
|
return {
|
|
14144
14170
|
id: r.id,
|
|
14145
14171
|
title: r.display_name,
|
|
@@ -14149,7 +14175,7 @@ function queryMobileAgents(limit = 50) {
|
|
|
14149
14175
|
harness: r.harness,
|
|
14150
14176
|
transport: r.transport,
|
|
14151
14177
|
state,
|
|
14152
|
-
statusLabel
|
|
14178
|
+
statusLabel,
|
|
14153
14179
|
sessionId: conversationIdForAgent(r.id),
|
|
14154
14180
|
lastActiveAt: lastMessageAt.get(r.id) ?? null
|
|
14155
14181
|
};
|
|
@@ -14271,7 +14297,7 @@ function queryMobileAgentDetail(agentId) {
|
|
|
14271
14297
|
ep.updated_at
|
|
14272
14298
|
FROM agents a
|
|
14273
14299
|
JOIN actors ac ON ac.id = a.id
|
|
14274
|
-
|
|
14300
|
+
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
14275
14301
|
WHERE a.id = ?`).get(agentId);
|
|
14276
14302
|
if (!row)
|
|
14277
14303
|
return null;
|
|
@@ -14283,8 +14309,7 @@ function queryMobileAgentDetail(agentId) {
|
|
|
14283
14309
|
try {
|
|
14284
14310
|
capabilities = row.capabilities_json ? JSON.parse(row.capabilities_json) : [];
|
|
14285
14311
|
} catch {}
|
|
14286
|
-
const
|
|
14287
|
-
WHERE state NOT IN ('completed','failed','cancelled')`).all().map((r) => r.target_agent_id));
|
|
14312
|
+
const executingAgentIds = queryExecutingAgentIds();
|
|
14288
14313
|
const activeFlights = db().prepare(`SELECT id, state, summary, started_at
|
|
14289
14314
|
FROM flights
|
|
14290
14315
|
WHERE target_agent_id = ? AND state NOT IN ('completed','failed','cancelled')
|
|
@@ -14308,9 +14333,9 @@ function queryMobileAgentDetail(agentId) {
|
|
|
14308
14333
|
const msgRow = db().prepare(`SELECT COUNT(*) AS cnt FROM messages WHERE conversation_id = ?`).get(conversationIdForAgent(agentId));
|
|
14309
14334
|
const messageCount = msgRow?.cnt ?? 0;
|
|
14310
14335
|
const lastMessageAt = db().prepare(`SELECT MAX(created_at) AS last_at FROM messages WHERE actor_id = ?`).get(agentId)?.last_at ?? null;
|
|
14311
|
-
const isWorking =
|
|
14312
|
-
const state =
|
|
14313
|
-
const statusLabel =
|
|
14336
|
+
const isWorking = executingAgentIds.has(row.id);
|
|
14337
|
+
const state = summarizeAgentState(row.state, isWorking);
|
|
14338
|
+
const statusLabel = summarizeAgentStatusLabel(row.state, isWorking);
|
|
14314
14339
|
return {
|
|
14315
14340
|
id: row.id,
|
|
14316
14341
|
title: row.display_name,
|
|
@@ -14320,7 +14345,7 @@ function queryMobileAgentDetail(agentId) {
|
|
|
14320
14345
|
harness: row.harness,
|
|
14321
14346
|
transport: row.transport,
|
|
14322
14347
|
state,
|
|
14323
|
-
statusLabel
|
|
14348
|
+
statusLabel,
|
|
14324
14349
|
sessionId: conversationIdForAgent(row.id),
|
|
14325
14350
|
lastActiveAt: lastMessageAt,
|
|
14326
14351
|
cwd: compact(row.cwd),
|
|
@@ -14429,7 +14454,7 @@ function endpointForAgent(snapshot, agentId) {
|
|
|
14429
14454
|
function buildMobileAgentSummary(snapshot, agent) {
|
|
14430
14455
|
const endpoint = endpointForAgent(snapshot, agent.id);
|
|
14431
14456
|
const flights = Object.values(snapshot.flights).filter((flight) => flight.targetAgentId === agent.id);
|
|
14432
|
-
const hasWorkingFlight = flights.some((flight) =>
|
|
14457
|
+
const hasWorkingFlight = flights.some((flight) => flight.state === "running");
|
|
14433
14458
|
const lastAuthoredMessageAt = Object.values(snapshot.messages).filter((message) => message.actorId === agent.id).reduce((latest, message) => {
|
|
14434
14459
|
const createdAt = normalizeTimestamp(message.createdAt);
|
|
14435
14460
|
return typeof createdAt === "number" && (!latest || createdAt > latest) ? createdAt : latest;
|
|
@@ -14444,7 +14469,7 @@ function buildMobileAgentSummary(snapshot, agent) {
|
|
|
14444
14469
|
harness: endpoint?.harness ?? null,
|
|
14445
14470
|
transport: endpoint?.transport ?? null,
|
|
14446
14471
|
state,
|
|
14447
|
-
statusLabel:
|
|
14472
|
+
statusLabel: state === "working" ? "Working" : state === "available" ? "Available" : "Offline",
|
|
14448
14473
|
sessionId: endpoint?.sessionId ?? null,
|
|
14449
14474
|
lastActiveAt: lastAuthoredMessageAt
|
|
14450
14475
|
};
|
|
@@ -13863,6 +13863,32 @@ function coerceNumber(value) {
|
|
|
13863
13863
|
}
|
|
13864
13864
|
return null;
|
|
13865
13865
|
}
|
|
13866
|
+
function isExecutingFlightState(state2) {
|
|
13867
|
+
return state2 === "running";
|
|
13868
|
+
}
|
|
13869
|
+
var LATEST_AGENT_ENDPOINT_JOIN = `LEFT JOIN agent_endpoints ep ON ep.id = (
|
|
13870
|
+
SELECT ep2.id
|
|
13871
|
+
FROM agent_endpoints ep2
|
|
13872
|
+
WHERE ep2.agent_id = a.id
|
|
13873
|
+
ORDER BY ep2.updated_at DESC
|
|
13874
|
+
LIMIT 1
|
|
13875
|
+
)`;
|
|
13876
|
+
function queryExecutingAgentIds() {
|
|
13877
|
+
return new Set(db().prepare(`SELECT DISTINCT target_agent_id FROM flights
|
|
13878
|
+
WHERE state = 'running'`).all().map((row) => row.target_agent_id));
|
|
13879
|
+
}
|
|
13880
|
+
function summarizeAgentState(rawState, isWorking) {
|
|
13881
|
+
if (isWorking) {
|
|
13882
|
+
return "working";
|
|
13883
|
+
}
|
|
13884
|
+
return rawState && rawState !== "offline" ? "available" : "offline";
|
|
13885
|
+
}
|
|
13886
|
+
function isDuplicateActivityFeedItem(previous, next) {
|
|
13887
|
+
if (!previous) {
|
|
13888
|
+
return false;
|
|
13889
|
+
}
|
|
13890
|
+
return previous.kind === next.kind && previous.title === next.title && previous.summary === next.summary && previous.conversationId === next.conversationId && Math.abs(previous.ts - next.ts) <= 5000;
|
|
13891
|
+
}
|
|
13866
13892
|
function workPhaseFromFlightState(state2) {
|
|
13867
13893
|
switch (state2) {
|
|
13868
13894
|
case "queued":
|
|
@@ -13953,6 +13979,7 @@ function projectWorkItemRow(row) {
|
|
|
13953
13979
|
};
|
|
13954
13980
|
}
|
|
13955
13981
|
function queryAgents(limit = 50) {
|
|
13982
|
+
const executingAgentIds = queryExecutingAgentIds();
|
|
13956
13983
|
const rows = db().prepare(`SELECT
|
|
13957
13984
|
a.id,
|
|
13958
13985
|
ac.display_name AS name,
|
|
@@ -13970,9 +13997,9 @@ function queryAgents(limit = 50) {
|
|
|
13970
13997
|
ep.updated_at
|
|
13971
13998
|
FROM agents a
|
|
13972
13999
|
JOIN actors ac ON ac.id = a.id
|
|
13973
|
-
|
|
14000
|
+
${LATEST_AGENT_ENDPOINT_JOIN}
|
|
13974
14001
|
WHERE COALESCE(json_extract(a.metadata_json, '$.retiredFromFleet'), 0) != 1
|
|
13975
|
-
ORDER BY ep.updated_at DESC
|
|
14002
|
+
ORDER BY COALESCE(ep.updated_at, 0) DESC, ac.display_name ASC
|
|
13976
14003
|
LIMIT ?`).all(limit);
|
|
13977
14004
|
return rows.map((r) => {
|
|
13978
14005
|
let capabilities = [];
|
|
@@ -13989,7 +14016,7 @@ function queryAgents(limit = 50) {
|
|
|
13989
14016
|
handle: r.handle,
|
|
13990
14017
|
agentClass: r.agent_class,
|
|
13991
14018
|
harness: r.harness,
|
|
13992
|
-
state: r.state,
|
|
14019
|
+
state: summarizeAgentState(r.state, executingAgentIds.has(r.id)),
|
|
13993
14020
|
projectRoot: compact(r.project_root),
|
|
13994
14021
|
cwd: compact(r.cwd),
|
|
13995
14022
|
updatedAt: r.updated_at,
|
|
@@ -14015,9 +14042,14 @@ function queryActivity(limit = 60) {
|
|
|
14015
14042
|
ai.workspace_root
|
|
14016
14043
|
FROM activity_items ai
|
|
14017
14044
|
LEFT JOIN actors ac ON ac.id = ai.actor_id
|
|
14045
|
+
WHERE ai.kind != 'ask_replied'
|
|
14046
|
+
AND NOT (
|
|
14047
|
+
ai.kind = 'flight_updated'
|
|
14048
|
+
AND COALESCE(ai.summary, '') LIKE 'Stale running flight reconciled:%'
|
|
14049
|
+
)
|
|
14018
14050
|
ORDER BY ai.ts DESC
|
|
14019
14051
|
LIMIT ?`).all(limit);
|
|
14020
|
-
|
|
14052
|
+
const items = rows.map((r) => ({
|
|
14021
14053
|
id: r.id,
|
|
14022
14054
|
kind: r.kind,
|
|
14023
14055
|
ts: r.ts,
|
|
@@ -14027,6 +14059,7 @@ function queryActivity(limit = 60) {
|
|
|
14027
14059
|
conversationId: r.conversation_id,
|
|
14028
14060
|
workspaceRoot: compact(r.workspace_root)
|
|
14029
14061
|
}));
|
|
14062
|
+
return items.filter((item, index) => !isDuplicateActivityFeedItem(items[index - 1] ?? null, item));
|
|
14030
14063
|
}
|
|
14031
14064
|
function queryRecentMessages(limit = 80) {
|
|
14032
14065
|
const rows = db().prepare(`SELECT
|
|
@@ -14175,6 +14208,7 @@ function queryFleetObservable(agentRow) {
|
|
|
14175
14208
|
});
|
|
14176
14209
|
const flightRows = queryFleetFlightRows(agentRow.id);
|
|
14177
14210
|
const latestFlight = flightRows[0] ?? null;
|
|
14211
|
+
const isWorking = activeFlights.some((flight) => isExecutingFlightState(flight.state));
|
|
14178
14212
|
const workStats = db().prepare(`SELECT
|
|
14179
14213
|
COUNT(*) AS active_work_count,
|
|
14180
14214
|
MAX(CASE WHEN state IN ('waiting','review') OR acceptance_state = 'pending' THEN 1 ELSE 0 END) AS attention_work_count,
|
|
@@ -14222,7 +14256,7 @@ function queryFleetObservable(agentRow) {
|
|
|
14222
14256
|
role,
|
|
14223
14257
|
harness: agentRow.harness,
|
|
14224
14258
|
transport: agentRow.transport,
|
|
14225
|
-
state: agentRow.state,
|
|
14259
|
+
state: summarizeAgentState(agentRow.state, isWorking),
|
|
14226
14260
|
attention,
|
|
14227
14261
|
conversationId,
|
|
14228
14262
|
sessionId: agentRow.session_id,
|
|
@@ -19390,6 +19390,15 @@ function coerceNumber(value) {
|
|
|
19390
19390
|
}
|
|
19391
19391
|
return null;
|
|
19392
19392
|
}
|
|
19393
|
+
function isExecutingFlightState(state4) {
|
|
19394
|
+
return state4 === "running";
|
|
19395
|
+
}
|
|
19396
|
+
function summarizeAgentState(rawState, isWorking) {
|
|
19397
|
+
if (isWorking) {
|
|
19398
|
+
return "working";
|
|
19399
|
+
}
|
|
19400
|
+
return rawState && rawState !== "offline" ? "available" : "offline";
|
|
19401
|
+
}
|
|
19393
19402
|
function parseFleetCapabilities(value) {
|
|
19394
19403
|
if (!value)
|
|
19395
19404
|
return [];
|
|
@@ -19516,6 +19525,7 @@ function queryFleetObservable(agentRow) {
|
|
|
19516
19525
|
});
|
|
19517
19526
|
const flightRows = queryFleetFlightRows(agentRow.id);
|
|
19518
19527
|
const latestFlight = flightRows[0] ?? null;
|
|
19528
|
+
const isWorking = activeFlights.some((flight) => isExecutingFlightState(flight.state));
|
|
19519
19529
|
const workStats = db().prepare(`SELECT
|
|
19520
19530
|
COUNT(*) AS active_work_count,
|
|
19521
19531
|
MAX(CASE WHEN state IN ('waiting','review') OR acceptance_state = 'pending' THEN 1 ELSE 0 END) AS attention_work_count,
|
|
@@ -19563,7 +19573,7 @@ function queryFleetObservable(agentRow) {
|
|
|
19563
19573
|
role,
|
|
19564
19574
|
harness: agentRow.harness,
|
|
19565
19575
|
transport: agentRow.transport,
|
|
19566
|
-
state: agentRow.state,
|
|
19576
|
+
state: summarizeAgentState(agentRow.state, isWorking),
|
|
19567
19577
|
attention,
|
|
19568
19578
|
conversationId,
|
|
19569
19579
|
sessionId: agentRow.session_id,
|
|
@@ -19803,7 +19813,7 @@ function endpointForAgent(snapshot, agentId) {
|
|
|
19803
19813
|
function buildMobileAgentSummary(snapshot, agent) {
|
|
19804
19814
|
const endpoint = endpointForAgent(snapshot, agent.id);
|
|
19805
19815
|
const flights = Object.values(snapshot.flights).filter((flight) => flight.targetAgentId === agent.id);
|
|
19806
|
-
const hasWorkingFlight = flights.some((flight) =>
|
|
19816
|
+
const hasWorkingFlight = flights.some((flight) => flight.state === "running");
|
|
19807
19817
|
const lastAuthoredMessageAt = Object.values(snapshot.messages).filter((message) => message.actorId === agent.id).reduce((latest, message) => {
|
|
19808
19818
|
const createdAt = normalizeTimestamp5(message.createdAt);
|
|
19809
19819
|
return typeof createdAt === "number" && (!latest || createdAt > latest) ? createdAt : latest;
|
|
@@ -19818,7 +19828,7 @@ function buildMobileAgentSummary(snapshot, agent) {
|
|
|
19818
19828
|
harness: endpoint?.harness ?? null,
|
|
19819
19829
|
transport: endpoint?.transport ?? null,
|
|
19820
19830
|
state: state4,
|
|
19821
|
-
statusLabel:
|
|
19831
|
+
statusLabel: state4 === "working" ? "Working" : state4 === "available" ? "Available" : "Offline",
|
|
19822
19832
|
sessionId: endpoint?.sessionId ?? null,
|
|
19823
19833
|
lastActiveAt: lastAuthoredMessageAt
|
|
19824
19834
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openscout/scout",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.49",
|
|
4
4
|
"description": "Published Scout package that installs the `scout` command",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@openscout/runtime": "0.2.
|
|
26
|
+
"@openscout/runtime": "0.2.49"
|
|
27
27
|
}
|
|
28
28
|
}
|