@openscout/scout 0.2.56 → 0.2.57
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/dist/client/assets/{arc.es-Cs--6ecm.js → arc.es-Ccqmb9Pq.js} +1 -1
- package/dist/client/assets/index-CN8PCsrs.css +1 -0
- package/dist/client/assets/index-X8QwrbtL.js +140 -0
- package/dist/client/index.html +3 -3
- package/dist/main.mjs +9 -1
- package/dist/pair-supervisor.mjs +8 -0
- package/dist/scout-control-plane-web.mjs +202 -130
- package/package.json +2 -2
- package/dist/client/assets/index-DvJjuWtM.js +0 -146
- package/dist/client/assets/index-MaClzcbW.css +0 -1
package/dist/client/index.html
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
<title>Scout</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
|
-
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&family=Spectral:wght@500;600&display=swap" rel="stylesheet" />
|
|
10
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter+Tight:wght@400;500;600&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&family=Spectral:wght@500;600&display=swap" rel="stylesheet" />
|
|
10
|
+
<script type="module" crossorigin src="/assets/index-X8QwrbtL.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CN8PCsrs.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root"></div>
|
package/dist/main.mjs
CHANGED
|
@@ -49339,6 +49339,12 @@ function compact(p) {
|
|
|
49339
49339
|
return null;
|
|
49340
49340
|
return p.startsWith(HOME) ? `~${p.slice(HOME.length)}` : p;
|
|
49341
49341
|
}
|
|
49342
|
+
function sqlQuoteLiteral(value) {
|
|
49343
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
49344
|
+
}
|
|
49345
|
+
function sqlStringList(values) {
|
|
49346
|
+
return `(${values.map(sqlQuoteLiteral).join(",")})`;
|
|
49347
|
+
}
|
|
49342
49348
|
function queryExecutingAgentIds() {
|
|
49343
49349
|
return new Set(db().prepare(`SELECT DISTINCT target_agent_id FROM flights
|
|
49344
49350
|
WHERE state = 'running'`).all().map((row) => row.target_agent_id));
|
|
@@ -49588,9 +49594,11 @@ var _db = null, HOME, LATEST_AGENT_ENDPOINT_JOIN = `LEFT JOIN agent_endpoints ep
|
|
|
49588
49594
|
WHERE ep2.agent_id = a.id
|
|
49589
49595
|
ORDER BY ep2.updated_at DESC
|
|
49590
49596
|
LIMIT 1
|
|
49591
|
-
)
|
|
49597
|
+
)`, ACTIVE_FLIGHT_STATES_SQL, ACTIVE_WORK_STATES_SQL;
|
|
49592
49598
|
var init_db_queries = __esm(() => {
|
|
49593
49599
|
HOME = homedir17();
|
|
49600
|
+
ACTIVE_FLIGHT_STATES_SQL = sqlStringList(["running", "waking", "waiting", "queued"]);
|
|
49601
|
+
ACTIVE_WORK_STATES_SQL = sqlStringList(["open", "working", "waiting", "review"]);
|
|
49594
49602
|
});
|
|
49595
49603
|
|
|
49596
49604
|
// ../../apps/desktop/src/core/mobile/service.ts
|
package/dist/pair-supervisor.mjs
CHANGED
|
@@ -15050,6 +15050,12 @@ function compact(p) {
|
|
|
15050
15050
|
return null;
|
|
15051
15051
|
return p.startsWith(HOME) ? `~${p.slice(HOME.length)}` : p;
|
|
15052
15052
|
}
|
|
15053
|
+
function sqlQuoteLiteral(value) {
|
|
15054
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
15055
|
+
}
|
|
15056
|
+
function sqlStringList(values) {
|
|
15057
|
+
return `(${values.map(sqlQuoteLiteral).join(",")})`;
|
|
15058
|
+
}
|
|
15053
15059
|
var LATEST_AGENT_ENDPOINT_JOIN = `LEFT JOIN agent_endpoints ep ON ep.id = (
|
|
15054
15060
|
SELECT ep2.id
|
|
15055
15061
|
FROM agent_endpoints ep2
|
|
@@ -15077,6 +15083,8 @@ function summarizeAgentStatusLabel(rawState, isWorking) {
|
|
|
15077
15083
|
return "Offline";
|
|
15078
15084
|
}
|
|
15079
15085
|
}
|
|
15086
|
+
var ACTIVE_FLIGHT_STATES_SQL = sqlStringList(["running", "waking", "waiting", "queued"]);
|
|
15087
|
+
var ACTIVE_WORK_STATES_SQL = sqlStringList(["open", "working", "waiting", "review"]);
|
|
15080
15088
|
function conversationIdForAgent(agentId) {
|
|
15081
15089
|
return `dm.operator.${agentId}`;
|
|
15082
15090
|
}
|
|
@@ -14987,94 +14987,6 @@ async function controlScoutWebPairingService(action, currentDirectory) {
|
|
|
14987
14987
|
});
|
|
14988
14988
|
}
|
|
14989
14989
|
|
|
14990
|
-
// node_modules/.bun/hono@4.12.10/node_modules/hono/dist/middleware/cors/index.js
|
|
14991
|
-
var cors = (options) => {
|
|
14992
|
-
const defaults = {
|
|
14993
|
-
origin: "*",
|
|
14994
|
-
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
|
|
14995
|
-
allowHeaders: [],
|
|
14996
|
-
exposeHeaders: []
|
|
14997
|
-
};
|
|
14998
|
-
const opts = {
|
|
14999
|
-
...defaults,
|
|
15000
|
-
...options
|
|
15001
|
-
};
|
|
15002
|
-
const findAllowOrigin = ((optsOrigin) => {
|
|
15003
|
-
if (typeof optsOrigin === "string") {
|
|
15004
|
-
if (optsOrigin === "*") {
|
|
15005
|
-
if (opts.credentials) {
|
|
15006
|
-
return (origin) => origin || null;
|
|
15007
|
-
}
|
|
15008
|
-
return () => optsOrigin;
|
|
15009
|
-
} else {
|
|
15010
|
-
return (origin) => optsOrigin === origin ? origin : null;
|
|
15011
|
-
}
|
|
15012
|
-
} else if (typeof optsOrigin === "function") {
|
|
15013
|
-
return optsOrigin;
|
|
15014
|
-
} else {
|
|
15015
|
-
return (origin) => optsOrigin.includes(origin) ? origin : null;
|
|
15016
|
-
}
|
|
15017
|
-
})(opts.origin);
|
|
15018
|
-
const findAllowMethods = ((optsAllowMethods) => {
|
|
15019
|
-
if (typeof optsAllowMethods === "function") {
|
|
15020
|
-
return optsAllowMethods;
|
|
15021
|
-
} else if (Array.isArray(optsAllowMethods)) {
|
|
15022
|
-
return () => optsAllowMethods;
|
|
15023
|
-
} else {
|
|
15024
|
-
return () => [];
|
|
15025
|
-
}
|
|
15026
|
-
})(opts.allowMethods);
|
|
15027
|
-
return async function cors2(c, next) {
|
|
15028
|
-
function set(key, value) {
|
|
15029
|
-
c.res.headers.set(key, value);
|
|
15030
|
-
}
|
|
15031
|
-
const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c);
|
|
15032
|
-
if (allowOrigin) {
|
|
15033
|
-
set("Access-Control-Allow-Origin", allowOrigin);
|
|
15034
|
-
}
|
|
15035
|
-
if (opts.credentials) {
|
|
15036
|
-
set("Access-Control-Allow-Credentials", "true");
|
|
15037
|
-
}
|
|
15038
|
-
if (opts.exposeHeaders?.length) {
|
|
15039
|
-
set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
|
|
15040
|
-
}
|
|
15041
|
-
if (c.req.method === "OPTIONS") {
|
|
15042
|
-
if (opts.origin !== "*" || opts.credentials) {
|
|
15043
|
-
set("Vary", "Origin");
|
|
15044
|
-
}
|
|
15045
|
-
if (opts.maxAge != null) {
|
|
15046
|
-
set("Access-Control-Max-Age", opts.maxAge.toString());
|
|
15047
|
-
}
|
|
15048
|
-
const allowMethods = await findAllowMethods(c.req.header("origin") || "", c);
|
|
15049
|
-
if (allowMethods.length) {
|
|
15050
|
-
set("Access-Control-Allow-Methods", allowMethods.join(","));
|
|
15051
|
-
}
|
|
15052
|
-
let headers = opts.allowHeaders;
|
|
15053
|
-
if (!headers?.length) {
|
|
15054
|
-
const requestHeaders = c.req.header("Access-Control-Request-Headers");
|
|
15055
|
-
if (requestHeaders) {
|
|
15056
|
-
headers = requestHeaders.split(/\s*,\s*/);
|
|
15057
|
-
}
|
|
15058
|
-
}
|
|
15059
|
-
if (headers?.length) {
|
|
15060
|
-
set("Access-Control-Allow-Headers", headers.join(","));
|
|
15061
|
-
c.res.headers.append("Vary", "Access-Control-Request-Headers");
|
|
15062
|
-
}
|
|
15063
|
-
c.res.headers.delete("Content-Length");
|
|
15064
|
-
c.res.headers.delete("Content-Type");
|
|
15065
|
-
return new Response(null, {
|
|
15066
|
-
headers: c.res.headers,
|
|
15067
|
-
status: 204,
|
|
15068
|
-
statusText: "No Content"
|
|
15069
|
-
});
|
|
15070
|
-
}
|
|
15071
|
-
await next();
|
|
15072
|
-
if (opts.origin !== "*" || opts.credentials) {
|
|
15073
|
-
c.header("Vary", "Origin", { append: true });
|
|
15074
|
-
}
|
|
15075
|
-
};
|
|
15076
|
-
};
|
|
15077
|
-
|
|
15078
14990
|
// node_modules/.bun/hono@4.12.10/node_modules/hono/dist/adapter/bun/serve-static.js
|
|
15079
14991
|
import { stat as stat3 } from "fs/promises";
|
|
15080
14992
|
import { join as join10 } from "path";
|
|
@@ -15347,6 +15259,40 @@ var upgradeWebSocket = defineWebSocketHelper((c, events2) => {
|
|
|
15347
15259
|
});
|
|
15348
15260
|
|
|
15349
15261
|
// packages/web/server/server-core.ts
|
|
15262
|
+
var LOOPBACK_IPV4_HOST_PATTERN = /^127(?:\.\d{1,3}){3}$/;
|
|
15263
|
+
function normalizeHostname(hostname2) {
|
|
15264
|
+
const trimmed = hostname2.trim().toLowerCase();
|
|
15265
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
15266
|
+
return trimmed.slice(1, -1);
|
|
15267
|
+
}
|
|
15268
|
+
return trimmed;
|
|
15269
|
+
}
|
|
15270
|
+
function isTrustedLoopbackHostname(hostname2) {
|
|
15271
|
+
const normalized = normalizeHostname(hostname2);
|
|
15272
|
+
return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "::1" || LOOPBACK_IPV4_HOST_PATTERN.test(normalized);
|
|
15273
|
+
}
|
|
15274
|
+
function isTrustedApiRequest(c) {
|
|
15275
|
+
const requestUrl = new URL(c.req.url);
|
|
15276
|
+
if (!isTrustedLoopbackHostname(requestUrl.hostname)) {
|
|
15277
|
+
return false;
|
|
15278
|
+
}
|
|
15279
|
+
const origin = c.req.header("origin");
|
|
15280
|
+
if (origin) {
|
|
15281
|
+
try {
|
|
15282
|
+
const originUrl = new URL(origin);
|
|
15283
|
+
if (!isTrustedLoopbackHostname(originUrl.hostname) || originUrl.origin !== requestUrl.origin) {
|
|
15284
|
+
return false;
|
|
15285
|
+
}
|
|
15286
|
+
} catch {
|
|
15287
|
+
return false;
|
|
15288
|
+
}
|
|
15289
|
+
}
|
|
15290
|
+
const fetchSite = c.req.header("sec-fetch-site")?.trim().toLowerCase();
|
|
15291
|
+
if (fetchSite && fetchSite !== "same-origin" && fetchSite !== "same-site" && fetchSite !== "none") {
|
|
15292
|
+
return false;
|
|
15293
|
+
}
|
|
15294
|
+
return true;
|
|
15295
|
+
}
|
|
15350
15296
|
function createCachedSnapshot(load, ttlMs) {
|
|
15351
15297
|
let inflight = null;
|
|
15352
15298
|
let cached = null;
|
|
@@ -15388,8 +15334,12 @@ function createCachedSnapshot(load, ttlMs) {
|
|
|
15388
15334
|
};
|
|
15389
15335
|
}
|
|
15390
15336
|
function installScoutApiMiddleware(app, label = "api") {
|
|
15391
|
-
app.use("/*", cors());
|
|
15392
15337
|
app.use("/api/*", async (c, next) => {
|
|
15338
|
+
if (!isTrustedApiRequest(c)) {
|
|
15339
|
+
return c.json({ error: "forbidden" }, 403);
|
|
15340
|
+
}
|
|
15341
|
+
c.header("Cross-Origin-Resource-Policy", "same-origin");
|
|
15342
|
+
c.header("X-Content-Type-Options", "nosniff");
|
|
15393
15343
|
try {
|
|
15394
15344
|
await next();
|
|
15395
15345
|
} catch (error) {
|
|
@@ -15612,6 +15562,22 @@ function coerceNumber(value) {
|
|
|
15612
15562
|
}
|
|
15613
15563
|
return null;
|
|
15614
15564
|
}
|
|
15565
|
+
function sqlJoinClauses(clauses, operator = "AND") {
|
|
15566
|
+
return clauses.filter((clause) => Boolean(clause)).join(` ${operator} `);
|
|
15567
|
+
}
|
|
15568
|
+
function sqlWhereClause(clauses, operator = "AND") {
|
|
15569
|
+
const joined = sqlJoinClauses(clauses, operator);
|
|
15570
|
+
return joined ? `WHERE ${joined}` : "";
|
|
15571
|
+
}
|
|
15572
|
+
function sqlPlaceholders(count) {
|
|
15573
|
+
return Array.from({ length: count }, () => "?").join(", ");
|
|
15574
|
+
}
|
|
15575
|
+
function sqlQuoteLiteral(value) {
|
|
15576
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
15577
|
+
}
|
|
15578
|
+
function sqlStringList(values) {
|
|
15579
|
+
return `(${values.map(sqlQuoteLiteral).join(",")})`;
|
|
15580
|
+
}
|
|
15615
15581
|
var LATEST_AGENT_ENDPOINT_JOIN = `LEFT JOIN agent_endpoints ep ON ep.id = (
|
|
15616
15582
|
SELECT ep2.id
|
|
15617
15583
|
FROM agent_endpoints ep2
|
|
@@ -15639,6 +15605,8 @@ function normalizeTimestampMs(value) {
|
|
|
15639
15605
|
}
|
|
15640
15606
|
return numeric < 1000000000000 ? numeric * 1000 : numeric;
|
|
15641
15607
|
}
|
|
15608
|
+
var ACTIVE_FLIGHT_STATES_SQL = sqlStringList(["running", "waking", "waiting", "queued"]);
|
|
15609
|
+
var ACTIVE_WORK_STATES_SQL = sqlStringList(["open", "working", "waiting", "review"]);
|
|
15642
15610
|
function isDuplicateActivityFeedItem(previous, next) {
|
|
15643
15611
|
if (!previous) {
|
|
15644
15612
|
return false;
|
|
@@ -15835,10 +15803,10 @@ function queryActivity(limit = 60) {
|
|
|
15835
15803
|
}
|
|
15836
15804
|
function queryRecentMessages(limit = 80, opts) {
|
|
15837
15805
|
const conversationIds = opts?.conversationId ? conversationIdAliases(opts.conversationId) : [];
|
|
15838
|
-
const where = [
|
|
15806
|
+
const where = sqlJoinClauses([
|
|
15839
15807
|
transientBrokerWorkingStatusPredicate("m"),
|
|
15840
|
-
conversationIds.length > 0 ? `m.conversation_id IN (${conversationIds.
|
|
15841
|
-
]
|
|
15808
|
+
conversationIds.length > 0 ? `m.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` : null
|
|
15809
|
+
]);
|
|
15842
15810
|
const rows = db().prepare(`SELECT
|
|
15843
15811
|
m.id,
|
|
15844
15812
|
m.conversation_id,
|
|
@@ -15873,14 +15841,13 @@ function queryRecentMessages(limit = 80, opts) {
|
|
|
15873
15841
|
});
|
|
15874
15842
|
}
|
|
15875
15843
|
function queryFlights(opts) {
|
|
15876
|
-
const activeStates = "('running','waking','waiting','queued')";
|
|
15877
15844
|
const conversationIds = opts?.conversationId ? conversationIdAliases(opts.conversationId) : [];
|
|
15878
|
-
const where = [
|
|
15879
|
-
opts?.activeOnly ? `f.state IN ${
|
|
15845
|
+
const where = sqlJoinClauses([
|
|
15846
|
+
opts?.activeOnly ? `f.state IN ${ACTIVE_FLIGHT_STATES_SQL}` : null,
|
|
15880
15847
|
opts?.agentId ? `f.target_agent_id = ?` : null,
|
|
15881
|
-
conversationIds.length > 0 ? `inv.conversation_id IN (${conversationIds.
|
|
15848
|
+
conversationIds.length > 0 ? `inv.conversation_id IN (${sqlPlaceholders(conversationIds.length)})` : null,
|
|
15882
15849
|
opts?.collaborationRecordId ? `inv.collaboration_record_id = ?` : null
|
|
15883
|
-
]
|
|
15850
|
+
]);
|
|
15884
15851
|
const sql = `SELECT
|
|
15885
15852
|
f.id,
|
|
15886
15853
|
f.invocation_id,
|
|
@@ -15895,7 +15862,7 @@ function queryFlights(opts) {
|
|
|
15895
15862
|
FROM flights f
|
|
15896
15863
|
JOIN invocations inv ON inv.id = f.invocation_id
|
|
15897
15864
|
LEFT JOIN actors ac ON ac.id = f.target_agent_id
|
|
15898
|
-
${where
|
|
15865
|
+
${sqlWhereClause([where])}
|
|
15899
15866
|
ORDER BY f.started_at DESC NULLS LAST
|
|
15900
15867
|
LIMIT 100`;
|
|
15901
15868
|
const params = [];
|
|
@@ -15920,7 +15887,6 @@ function queryFlights(opts) {
|
|
|
15920
15887
|
}));
|
|
15921
15888
|
}
|
|
15922
15889
|
function queryWorkItemById(id) {
|
|
15923
|
-
const activeStates = "('open','working','waiting','review')";
|
|
15924
15890
|
const sql = `SELECT
|
|
15925
15891
|
cr.id,
|
|
15926
15892
|
cr.title,
|
|
@@ -15943,7 +15909,7 @@ function queryWorkItemById(id) {
|
|
|
15943
15909
|
FROM collaboration_records child
|
|
15944
15910
|
WHERE child.parent_id = cr.id
|
|
15945
15911
|
AND child.kind = 'work_item'
|
|
15946
|
-
AND child.state IN ${
|
|
15912
|
+
AND child.state IN ${ACTIVE_WORK_STATES_SQL}
|
|
15947
15913
|
) AS active_child_work_count,
|
|
15948
15914
|
(
|
|
15949
15915
|
SELECT COUNT(*)
|
|
@@ -16131,12 +16097,11 @@ function queryWorkTimeline(workId) {
|
|
|
16131
16097
|
return items.slice(0, 80);
|
|
16132
16098
|
}
|
|
16133
16099
|
function queryWorkItems(opts) {
|
|
16134
|
-
const
|
|
16135
|
-
const where = [
|
|
16100
|
+
const where = sqlJoinClauses([
|
|
16136
16101
|
"cr.kind = 'work_item'",
|
|
16137
|
-
opts?.activeOnly !== false ? `cr.state IN ${
|
|
16102
|
+
opts?.activeOnly !== false ? `cr.state IN ${ACTIVE_WORK_STATES_SQL}` : null,
|
|
16138
16103
|
opts?.agentId ? "(cr.owner_id = ? OR cr.next_move_owner_id = ?)" : null
|
|
16139
|
-
]
|
|
16104
|
+
]);
|
|
16140
16105
|
const sql = `SELECT
|
|
16141
16106
|
cr.id,
|
|
16142
16107
|
cr.title,
|
|
@@ -16156,7 +16121,7 @@ function queryWorkItems(opts) {
|
|
|
16156
16121
|
FROM collaboration_records child
|
|
16157
16122
|
WHERE child.parent_id = cr.id
|
|
16158
16123
|
AND child.kind = 'work_item'
|
|
16159
|
-
AND child.state IN ${
|
|
16124
|
+
AND child.state IN ${ACTIVE_WORK_STATES_SQL}
|
|
16160
16125
|
) AS active_child_work_count,
|
|
16161
16126
|
(
|
|
16162
16127
|
SELECT COUNT(*)
|
|
@@ -16234,7 +16199,7 @@ function queryWorkItems(opts) {
|
|
|
16234
16199
|
FROM collaboration_records cr
|
|
16235
16200
|
LEFT JOIN actors owner ON owner.id = cr.owner_id
|
|
16236
16201
|
LEFT JOIN actors next ON next.id = cr.next_move_owner_id
|
|
16237
|
-
${where
|
|
16202
|
+
${sqlWhereClause([where])}
|
|
16238
16203
|
ORDER BY sort_ts DESC, cr.updated_at DESC
|
|
16239
16204
|
LIMIT ?`;
|
|
16240
16205
|
const limit = opts?.limit ?? 50;
|
|
@@ -16565,7 +16530,7 @@ function queryFleetActivity(opts) {
|
|
|
16565
16530
|
ai.session_id
|
|
16566
16531
|
FROM activity_items ai
|
|
16567
16532
|
LEFT JOIN actors ac ON ac.id = ai.actor_id
|
|
16568
|
-
${filters
|
|
16533
|
+
${sqlWhereClause(filters, "OR")}
|
|
16569
16534
|
ORDER BY ai.ts DESC
|
|
16570
16535
|
LIMIT ?`;
|
|
16571
16536
|
const rows = db().prepare(sql).all(...params, opts?.limit ?? 80);
|
|
@@ -16592,7 +16557,7 @@ function fleetStatusLabel(status) {
|
|
|
16592
16557
|
}
|
|
16593
16558
|
}
|
|
16594
16559
|
function queryFleetAskRows(requesterIds, limit) {
|
|
16595
|
-
const requesterClause = requesterIds.
|
|
16560
|
+
const requesterClause = sqlPlaceholders(requesterIds.length);
|
|
16596
16561
|
return db().prepare(`SELECT
|
|
16597
16562
|
inv.id AS invocation_id,
|
|
16598
16563
|
inv.requester_id,
|
|
@@ -16689,7 +16654,7 @@ function projectFleetAsk(row, requesterIdSet) {
|
|
|
16689
16654
|
};
|
|
16690
16655
|
}
|
|
16691
16656
|
function queryFleetAttentionRows(requesterIds, limit) {
|
|
16692
|
-
const requesterClause = requesterIds.
|
|
16657
|
+
const requesterClause = sqlPlaceholders(requesterIds.length);
|
|
16693
16658
|
return db().prepare(`SELECT
|
|
16694
16659
|
cr.kind AS record_kind,
|
|
16695
16660
|
cr.id AS record_id,
|
|
@@ -20071,6 +20036,9 @@ class ThreadEventPlane {
|
|
|
20071
20036
|
// packages/runtime/src/mobile-push.ts
|
|
20072
20037
|
init_support_paths();
|
|
20073
20038
|
// packages/web/server/core/observe/service.ts
|
|
20039
|
+
var HISTORY_SNAPSHOT_CACHE_LIMIT = 128;
|
|
20040
|
+
var historySnapshotCache = new Map;
|
|
20041
|
+
var OBSERVE_SUMMARY_TAIL_SIZE = 8;
|
|
20074
20042
|
function activeEndpoint(snapshot, agentId) {
|
|
20075
20043
|
const candidates = Object.values(snapshot.endpoints ?? {}).filter((endpoint) => endpoint.agentId === agentId);
|
|
20076
20044
|
const rank = (state) => {
|
|
@@ -20179,16 +20147,39 @@ function readHistorySnapshot(candidate) {
|
|
|
20179
20147
|
return null;
|
|
20180
20148
|
}
|
|
20181
20149
|
const stat5 = statSync4(candidate.path);
|
|
20150
|
+
const cached = historySnapshotCache.get(candidate.path);
|
|
20151
|
+
if (cached && cached.adapterType === candidate.adapterType && cached.mtimeMs === stat5.mtimeMs && cached.size === stat5.size) {
|
|
20152
|
+
return {
|
|
20153
|
+
historyPath: cached.historyPath,
|
|
20154
|
+
snapshot: cached.snapshot,
|
|
20155
|
+
timedEvents: cached.timedEvents
|
|
20156
|
+
};
|
|
20157
|
+
}
|
|
20182
20158
|
const replay = createHistorySessionSnapshot({
|
|
20183
20159
|
path: candidate.path,
|
|
20184
20160
|
content: readFileSync7(candidate.path, "utf8"),
|
|
20185
20161
|
adapterType: candidate.adapterType,
|
|
20186
20162
|
baseTimestampMs: stat5.mtimeMs
|
|
20187
20163
|
});
|
|
20188
|
-
|
|
20164
|
+
const nextEntry = {
|
|
20189
20165
|
historyPath: candidate.path,
|
|
20190
20166
|
snapshot: replay.snapshot,
|
|
20191
|
-
timedEvents: normalizeTimedEvents(replay.events)
|
|
20167
|
+
timedEvents: normalizeTimedEvents(replay.events),
|
|
20168
|
+
adapterType: candidate.adapterType,
|
|
20169
|
+
mtimeMs: stat5.mtimeMs,
|
|
20170
|
+
size: stat5.size
|
|
20171
|
+
};
|
|
20172
|
+
historySnapshotCache.set(candidate.path, nextEntry);
|
|
20173
|
+
if (historySnapshotCache.size > HISTORY_SNAPSHOT_CACHE_LIMIT) {
|
|
20174
|
+
const oldestKey = historySnapshotCache.keys().next().value;
|
|
20175
|
+
if (typeof oldestKey === "string") {
|
|
20176
|
+
historySnapshotCache.delete(oldestKey);
|
|
20177
|
+
}
|
|
20178
|
+
}
|
|
20179
|
+
return {
|
|
20180
|
+
historyPath: nextEntry.historyPath,
|
|
20181
|
+
snapshot: nextEntry.snapshot,
|
|
20182
|
+
timedEvents: nextEntry.timedEvents
|
|
20192
20183
|
};
|
|
20193
20184
|
}
|
|
20194
20185
|
async function readLiveSnapshot(endpoint) {
|
|
@@ -20570,8 +20561,7 @@ function unavailableObserveData(agent) {
|
|
|
20570
20561
|
live: false
|
|
20571
20562
|
};
|
|
20572
20563
|
}
|
|
20573
|
-
async function resolveSnapshotSource(agent) {
|
|
20574
|
-
const broker2 = await loadScoutBrokerContext();
|
|
20564
|
+
async function resolveSnapshotSource(agent, broker2) {
|
|
20575
20565
|
const endpoint = broker2 ? activeEndpoint(broker2.snapshot, agent.id) : null;
|
|
20576
20566
|
const liveSnapshot = await readLiveSnapshot(endpoint);
|
|
20577
20567
|
const live = Boolean(liveSnapshot && (liveSnapshot.currentTurnId || liveSnapshot.session.status === "active"));
|
|
@@ -20615,15 +20605,11 @@ async function resolveSnapshotSource(agent) {
|
|
|
20615
20605
|
sessionId: null
|
|
20616
20606
|
};
|
|
20617
20607
|
}
|
|
20618
|
-
async function
|
|
20619
|
-
const
|
|
20620
|
-
if (!agent) {
|
|
20621
|
-
return null;
|
|
20622
|
-
}
|
|
20623
|
-
const source = await resolveSnapshotSource(agent);
|
|
20608
|
+
async function buildAgentObservePayload(agent, broker2) {
|
|
20609
|
+
const source = await resolveSnapshotSource(agent, broker2);
|
|
20624
20610
|
if (source.source === "unavailable") {
|
|
20625
20611
|
return {
|
|
20626
|
-
agentId,
|
|
20612
|
+
agentId: agent.id,
|
|
20627
20613
|
source: "unavailable",
|
|
20628
20614
|
fidelity: "synthetic",
|
|
20629
20615
|
historyPath: null,
|
|
@@ -20634,7 +20620,7 @@ async function loadAgentObservePayload(agentId) {
|
|
|
20634
20620
|
}
|
|
20635
20621
|
const fidelity = source.timedEvents.length > 0 ? "timestamped" : "synthetic";
|
|
20636
20622
|
return {
|
|
20637
|
-
agentId,
|
|
20623
|
+
agentId: agent.id,
|
|
20638
20624
|
source: source.source,
|
|
20639
20625
|
fidelity,
|
|
20640
20626
|
historyPath: source.historyPath,
|
|
@@ -20643,6 +20629,33 @@ async function loadAgentObservePayload(agentId) {
|
|
|
20643
20629
|
data: buildObserveDataFromSnapshot(source.snapshot, source.timedEvents, source.live)
|
|
20644
20630
|
};
|
|
20645
20631
|
}
|
|
20632
|
+
async function loadAgentObservePayloadsInternal(agentIds) {
|
|
20633
|
+
const agents = queryAgents(200);
|
|
20634
|
+
const filteredAgents = agentIds && agentIds.length > 0 ? agents.filter((agent) => agentIds.includes(agent.id)) : agents;
|
|
20635
|
+
if (filteredAgents.length === 0) {
|
|
20636
|
+
return [];
|
|
20637
|
+
}
|
|
20638
|
+
const broker2 = await loadScoutBrokerContext();
|
|
20639
|
+
return await Promise.all(filteredAgents.map((agent) => buildAgentObservePayload(agent, broker2)));
|
|
20640
|
+
}
|
|
20641
|
+
function summarizeAgentObservePayload(payload) {
|
|
20642
|
+
return {
|
|
20643
|
+
...payload,
|
|
20644
|
+
data: {
|
|
20645
|
+
...payload.data,
|
|
20646
|
+
events: payload.data.events.slice(-OBSERVE_SUMMARY_TAIL_SIZE),
|
|
20647
|
+
files: []
|
|
20648
|
+
}
|
|
20649
|
+
};
|
|
20650
|
+
}
|
|
20651
|
+
async function loadAgentObserveSummaries(agentIds) {
|
|
20652
|
+
const payloads = await loadAgentObservePayloadsInternal(agentIds);
|
|
20653
|
+
return payloads.map(summarizeAgentObservePayload);
|
|
20654
|
+
}
|
|
20655
|
+
async function loadAgentObservePayload(agentId) {
|
|
20656
|
+
const payloads = await loadAgentObservePayloadsInternal([agentId]);
|
|
20657
|
+
return payloads[0] ?? null;
|
|
20658
|
+
}
|
|
20646
20659
|
|
|
20647
20660
|
// packages/web/server/core/mesh/service.ts
|
|
20648
20661
|
await init_broker_service();
|
|
@@ -20994,6 +21007,10 @@ async function createOpenScoutWebServer(options) {
|
|
|
20994
21007
|
app.get("/api/shell-state", async (c) => c.json(await shellStateCache.get()));
|
|
20995
21008
|
app.get("/api/shell-state/refresh", async (c) => c.json(await shellStateCache.refresh()));
|
|
20996
21009
|
app.get("/api/agents", (c) => c.json(queryAgents()));
|
|
21010
|
+
app.get("/api/observe/agents", async (c) => {
|
|
21011
|
+
const ids = c.req.query("ids")?.split(",").map((value) => value.trim()).filter((value) => value.length > 0);
|
|
21012
|
+
return c.json(await loadAgentObserveSummaries(ids));
|
|
21013
|
+
});
|
|
20997
21014
|
app.get("/api/agents/:id/observe", async (c) => {
|
|
20998
21015
|
const payload = await loadAgentObservePayload(c.req.param("id"));
|
|
20999
21016
|
return payload ? c.json(payload) : c.json({ error: "not found" }, 404);
|
|
@@ -21059,7 +21076,22 @@ async function createOpenScoutWebServer(options) {
|
|
|
21059
21076
|
}
|
|
21060
21077
|
});
|
|
21061
21078
|
app.get("/api/user", (c) => {
|
|
21062
|
-
|
|
21079
|
+
const config = loadUserConfig();
|
|
21080
|
+
return c.json({
|
|
21081
|
+
name: resolveOperatorName(),
|
|
21082
|
+
handle: config.handle ?? "",
|
|
21083
|
+
pronouns: config.pronouns ?? "",
|
|
21084
|
+
hue: config.hue ?? 195,
|
|
21085
|
+
bio: config.bio ?? "",
|
|
21086
|
+
timezone: config.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
21087
|
+
workingHours: config.workingHours ?? "08:00 \u2013 18:00",
|
|
21088
|
+
interruptThreshold: config.interruptThreshold ?? "blocking-only",
|
|
21089
|
+
batchWindow: config.batchWindow ?? 15,
|
|
21090
|
+
channel: config.channel ?? "here+mobile",
|
|
21091
|
+
verbosity: config.verbosity ?? "terse",
|
|
21092
|
+
tone: config.tone ?? "direct",
|
|
21093
|
+
quietHours: config.quietHours ?? "22:00 \u2013 07:00"
|
|
21094
|
+
});
|
|
21063
21095
|
});
|
|
21064
21096
|
app.get("/api/onboarding/state", async (c) => {
|
|
21065
21097
|
const hasLocalConfig = localConfigExists();
|
|
@@ -21135,15 +21167,53 @@ async function createOpenScoutWebServer(options) {
|
|
|
21135
21167
|
});
|
|
21136
21168
|
});
|
|
21137
21169
|
app.post("/api/user", async (c) => {
|
|
21138
|
-
const
|
|
21170
|
+
const body = await c.req.json();
|
|
21139
21171
|
const config = loadUserConfig();
|
|
21140
|
-
|
|
21141
|
-
|
|
21142
|
-
|
|
21143
|
-
|
|
21172
|
+
const stringFields = [
|
|
21173
|
+
"name",
|
|
21174
|
+
"handle",
|
|
21175
|
+
"pronouns",
|
|
21176
|
+
"bio",
|
|
21177
|
+
"timezone",
|
|
21178
|
+
"workingHours",
|
|
21179
|
+
"interruptThreshold",
|
|
21180
|
+
"channel",
|
|
21181
|
+
"verbosity",
|
|
21182
|
+
"tone",
|
|
21183
|
+
"quietHours"
|
|
21184
|
+
];
|
|
21185
|
+
for (const key of stringFields) {
|
|
21186
|
+
if (key in body) {
|
|
21187
|
+
const val = body[key];
|
|
21188
|
+
if (typeof val === "string" && val.trim()) {
|
|
21189
|
+
config[key] = val.trim();
|
|
21190
|
+
} else {
|
|
21191
|
+
delete config[key];
|
|
21192
|
+
}
|
|
21193
|
+
}
|
|
21194
|
+
}
|
|
21195
|
+
if ("hue" in body && typeof body.hue === "number") {
|
|
21196
|
+
config.hue = body.hue;
|
|
21197
|
+
}
|
|
21198
|
+
if ("batchWindow" in body && typeof body.batchWindow === "number") {
|
|
21199
|
+
config.batchWindow = body.batchWindow;
|
|
21144
21200
|
}
|
|
21145
21201
|
saveUserConfig(config);
|
|
21146
|
-
return c.json({
|
|
21202
|
+
return c.json({
|
|
21203
|
+
name: resolveOperatorName(),
|
|
21204
|
+
handle: config.handle ?? "",
|
|
21205
|
+
pronouns: config.pronouns ?? "",
|
|
21206
|
+
hue: config.hue ?? 195,
|
|
21207
|
+
bio: config.bio ?? "",
|
|
21208
|
+
timezone: config.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
21209
|
+
workingHours: config.workingHours ?? "08:00 \u2013 18:00",
|
|
21210
|
+
interruptThreshold: config.interruptThreshold ?? "blocking-only",
|
|
21211
|
+
batchWindow: config.batchWindow ?? 15,
|
|
21212
|
+
channel: config.channel ?? "here+mobile",
|
|
21213
|
+
verbosity: config.verbosity ?? "terse",
|
|
21214
|
+
tone: config.tone ?? "direct",
|
|
21215
|
+
quietHours: config.quietHours ?? "22:00 \u2013 07:00"
|
|
21216
|
+
});
|
|
21147
21217
|
});
|
|
21148
21218
|
app.post("/api/agents/:agentId/interrupt", async (c) => {
|
|
21149
21219
|
const agentId = c.req.param("agentId");
|
|
@@ -21623,6 +21693,7 @@ function destroyAllRelaySessions() {
|
|
|
21623
21693
|
|
|
21624
21694
|
// packages/web/server/index.ts
|
|
21625
21695
|
var port = Number(process.env.OPENSCOUT_WEB_PORT ?? process.env.SCOUT_WEB_PORT ?? "3200");
|
|
21696
|
+
var hostname2 = process.env.OPENSCOUT_WEB_HOST?.trim() || process.env.SCOUT_WEB_HOST?.trim() || "127.0.0.1";
|
|
21626
21697
|
var currentDirectory = process.env.OPENSCOUT_SETUP_CWD?.trim() || process.cwd();
|
|
21627
21698
|
var shellStateCacheTtlMs = Number.parseInt(process.env.OPENSCOUT_WEB_SHELL_CACHE_TTL_MS ?? "15000", 10);
|
|
21628
21699
|
function resolveStaticRoot2() {
|
|
@@ -21654,6 +21725,7 @@ var { app, warmupCaches } = await createOpenScoutWebServer({
|
|
|
21654
21725
|
var honoFetch = app.fetch;
|
|
21655
21726
|
var server = Bun.serve({
|
|
21656
21727
|
port,
|
|
21728
|
+
hostname: hostname2,
|
|
21657
21729
|
idleTimeout: idleTimeoutSeconds,
|
|
21658
21730
|
fetch(req, server2) {
|
|
21659
21731
|
const url = new URL(req.url);
|
|
@@ -21680,6 +21752,6 @@ var shutdown = () => {
|
|
|
21680
21752
|
};
|
|
21681
21753
|
process.on("SIGINT", shutdown);
|
|
21682
21754
|
process.on("SIGTERM", shutdown);
|
|
21683
|
-
console.log(`OpenScout Web -> http
|
|
21684
|
-
console.log(`Relay WebSocket -> ws
|
|
21755
|
+
console.log(`OpenScout Web -> http://${hostname2}:${server.port}`);
|
|
21756
|
+
console.log(`Relay WebSocket -> ws://${hostname2}:${server.port}`);
|
|
21685
21757
|
warmupCaches();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openscout/scout",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.57",
|
|
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.57"
|
|
27
27
|
}
|
|
28
28
|
}
|