unbrowse 2.1.2 → 2.1.3
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/cli.js +1 -1
- package/dist/index.js +35 -11
- package/package.json +1 -1
- package/runtime-src/api/routes.ts +1 -1
- package/runtime-src/cli.ts +1 -1
- package/runtime-src/orchestrator/index.ts +64 -14
package/dist/cli.js
CHANGED
|
@@ -1302,7 +1302,7 @@ async function handleMessage(msg, unbrowseBin, timeoutMs) {
|
|
|
1302
1302
|
loadEnv({ quiet: true });
|
|
1303
1303
|
loadEnv({ path: ".env.runtime", quiet: true });
|
|
1304
1304
|
var BASE_URL = process.env.UNBROWSE_URL || "http://localhost:6969";
|
|
1305
|
-
var CLI_CLIENT_ID = process.env.UNBROWSE_CLIENT_ID ||
|
|
1305
|
+
var CLI_CLIENT_ID = process.env.UNBROWSE_CLIENT_ID || "cli-local";
|
|
1306
1306
|
function parseArgs(argv) {
|
|
1307
1307
|
const raw = argv.slice(2);
|
|
1308
1308
|
const command = raw[0] && !raw[0].startsWith("--") ? raw[0] : "help";
|
package/dist/index.js
CHANGED
|
@@ -14177,6 +14177,25 @@ function promoteResultSnapshot(cacheKey, skill, endpointId, result, trace, respo
|
|
|
14177
14177
|
expires: Date.now() + ROUTE_CACHE_TTL
|
|
14178
14178
|
});
|
|
14179
14179
|
}
|
|
14180
|
+
function buildCachedResultResponse(cached, source, timing) {
|
|
14181
|
+
const now = new Date().toISOString();
|
|
14182
|
+
return {
|
|
14183
|
+
result: cached.result,
|
|
14184
|
+
trace: {
|
|
14185
|
+
...cached.trace,
|
|
14186
|
+
trace_id: nanoid6(),
|
|
14187
|
+
started_at: now,
|
|
14188
|
+
completed_at: now,
|
|
14189
|
+
endpoint_id: cached.endpointId ?? cached.trace.endpoint_id,
|
|
14190
|
+
skill_id: cached.skill.skill_id
|
|
14191
|
+
},
|
|
14192
|
+
source,
|
|
14193
|
+
skill: cached.skill,
|
|
14194
|
+
timing,
|
|
14195
|
+
response_schema: cached.response_schema,
|
|
14196
|
+
extraction_hints: cached.extraction_hints
|
|
14197
|
+
};
|
|
14198
|
+
}
|
|
14180
14199
|
function invalidateResolveCacheEntries(cacheKeys, domainKeys = []) {
|
|
14181
14200
|
let routeCacheDirty = false;
|
|
14182
14201
|
let domainCacheDirty = false;
|
|
@@ -14401,6 +14420,11 @@ async function withDomainCaptureLock(domain, fn) {
|
|
|
14401
14420
|
function shouldFallbackToLiveCaptureAfterAutoexecFailure(autoexecFailedAll, contextUrl) {
|
|
14402
14421
|
return autoexecFailedAll && !!contextUrl;
|
|
14403
14422
|
}
|
|
14423
|
+
function shouldReuseRouteResultSnapshot(cached, intent, contextUrl, now = Date.now()) {
|
|
14424
|
+
if (cached.expires <= now)
|
|
14425
|
+
return false;
|
|
14426
|
+
return isCachedSkillRelevantForIntent(cached.skill, intent, contextUrl);
|
|
14427
|
+
}
|
|
14404
14428
|
function computeCompositeScore(embeddingScore, skill) {
|
|
14405
14429
|
const reliabilities = skill.endpoints.map((e) => e.reliability_score);
|
|
14406
14430
|
const avgReliability = reliabilities.length > 0 ? reliabilities.reduce((a, b) => a + b, 0) / reliabilities.length : 0.5;
|
|
@@ -15328,18 +15352,18 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
|
|
|
15328
15352
|
if (!forceCapture && !agentChoseEndpoint) {
|
|
15329
15353
|
const cachedResult = routeResultCache.get(cacheKey);
|
|
15330
15354
|
if (cachedResult) {
|
|
15331
|
-
if (
|
|
15355
|
+
if (!shouldReuseRouteResultSnapshot(cachedResult, intent, context?.url)) {
|
|
15332
15356
|
routeResultCache.delete(cacheKey);
|
|
15333
15357
|
} else {
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15358
|
+
timing.cache_hit = true;
|
|
15359
|
+
writeDebugTrace("resolve", {
|
|
15360
|
+
...decisionTrace,
|
|
15361
|
+
outcome: "route_result_cache_hit",
|
|
15362
|
+
source: "route-cache",
|
|
15363
|
+
skill_id: cachedResult.skill.skill_id,
|
|
15364
|
+
selected_endpoint_id: cachedResult.endpointId ?? cachedResult.trace.endpoint_id
|
|
15365
|
+
});
|
|
15366
|
+
return buildCachedResultResponse(cachedResult, "marketplace", finalize2("route-cache", cachedResult.result, cachedResult.skill.skill_id, cachedResult.skill, cachedResult.trace));
|
|
15343
15367
|
}
|
|
15344
15368
|
}
|
|
15345
15369
|
}
|
|
@@ -16202,7 +16226,7 @@ async function fetchStats() {
|
|
|
16202
16226
|
return data;
|
|
16203
16227
|
}
|
|
16204
16228
|
async function registerRoutes(app) {
|
|
16205
|
-
const clientScopeFor = (req) => typeof req.headers["x-unbrowse-client-id"] === "string" && req.headers["x-unbrowse-client-id"].trim() ? req.headers["x-unbrowse-client-id"].trim() :
|
|
16229
|
+
const clientScopeFor = (req) => typeof req.headers["x-unbrowse-client-id"] === "string" && req.headers["x-unbrowse-client-id"].trim() ? req.headers["x-unbrowse-client-id"].trim() : "global";
|
|
16206
16230
|
app.addHook("onRequest", async (req, reply) => {
|
|
16207
16231
|
if (req.url === "/health" || req.url === "/v1/stats")
|
|
16208
16232
|
return;
|
package/package.json
CHANGED
|
@@ -141,7 +141,7 @@ export async function registerRoutes(app: FastifyInstance) {
|
|
|
141
141
|
const clientScopeFor = (req: { headers: Record<string, unknown>; id: string }) =>
|
|
142
142
|
(typeof req.headers["x-unbrowse-client-id"] === "string" && req.headers["x-unbrowse-client-id"].trim())
|
|
143
143
|
? req.headers["x-unbrowse-client-id"].trim()
|
|
144
|
-
:
|
|
144
|
+
: "global";
|
|
145
145
|
|
|
146
146
|
// Auth gate: block all routes except /health when no API key is configured
|
|
147
147
|
app.addHook("onRequest", async (req, reply) => {
|
package/runtime-src/cli.ts
CHANGED
|
@@ -18,7 +18,7 @@ loadEnv({ quiet: true });
|
|
|
18
18
|
loadEnv({ path: ".env.runtime", quiet: true });
|
|
19
19
|
|
|
20
20
|
const BASE_URL = process.env.UNBROWSE_URL || "http://localhost:6969";
|
|
21
|
-
const CLI_CLIENT_ID = process.env.UNBROWSE_CLIENT_ID ||
|
|
21
|
+
const CLI_CLIENT_ID = process.env.UNBROWSE_CLIENT_ID || "cli-local";
|
|
22
22
|
|
|
23
23
|
// ---------------------------------------------------------------------------
|
|
24
24
|
// Arg parser
|
|
@@ -329,6 +329,37 @@ function promoteResultSnapshot(
|
|
|
329
329
|
});
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
function buildCachedResultResponse(
|
|
333
|
+
cached: {
|
|
334
|
+
skill: SkillManifest;
|
|
335
|
+
endpointId?: string;
|
|
336
|
+
result: unknown;
|
|
337
|
+
trace: ExecutionTrace;
|
|
338
|
+
response_schema?: ResponseSchema;
|
|
339
|
+
extraction_hints?: OrchestratorResult["extraction_hints"];
|
|
340
|
+
},
|
|
341
|
+
source: "marketplace" | "live-capture",
|
|
342
|
+
timing: OrchestrationTiming,
|
|
343
|
+
): OrchestratorResult {
|
|
344
|
+
const now = new Date().toISOString();
|
|
345
|
+
return {
|
|
346
|
+
result: cached.result,
|
|
347
|
+
trace: {
|
|
348
|
+
...cached.trace,
|
|
349
|
+
trace_id: nanoid(),
|
|
350
|
+
started_at: now,
|
|
351
|
+
completed_at: now,
|
|
352
|
+
endpoint_id: cached.endpointId ?? cached.trace.endpoint_id,
|
|
353
|
+
skill_id: cached.skill.skill_id,
|
|
354
|
+
},
|
|
355
|
+
source,
|
|
356
|
+
skill: cached.skill,
|
|
357
|
+
timing,
|
|
358
|
+
response_schema: cached.response_schema,
|
|
359
|
+
extraction_hints: cached.extraction_hints,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
332
363
|
function invalidateResolveCacheEntries(cacheKeys: string[], domainKeys: string[] = []): void {
|
|
333
364
|
let routeCacheDirty = false;
|
|
334
365
|
let domainCacheDirty = false;
|
|
@@ -670,6 +701,19 @@ export function shouldFallbackToLiveCaptureAfterAutoexecFailure(
|
|
|
670
701
|
return autoexecFailedAll && !!contextUrl;
|
|
671
702
|
}
|
|
672
703
|
|
|
704
|
+
export function shouldReuseRouteResultSnapshot(
|
|
705
|
+
cached: {
|
|
706
|
+
expires: number;
|
|
707
|
+
skill: SkillManifest;
|
|
708
|
+
},
|
|
709
|
+
intent: string,
|
|
710
|
+
contextUrl?: string,
|
|
711
|
+
now = Date.now(),
|
|
712
|
+
): boolean {
|
|
713
|
+
if (cached.expires <= now) return false;
|
|
714
|
+
return isCachedSkillRelevantForIntent(cached.skill, intent, contextUrl);
|
|
715
|
+
}
|
|
716
|
+
|
|
673
717
|
function computeCompositeScore(embeddingScore: number, skill: SkillManifest): number {
|
|
674
718
|
// Average reliability across endpoints
|
|
675
719
|
const reliabilities = skill.endpoints.map((e) => e.reliability_score);
|
|
@@ -1940,22 +1984,28 @@ export async function resolveAndExecute(
|
|
|
1940
1984
|
if (!forceCapture && !agentChoseEndpoint) {
|
|
1941
1985
|
const cachedResult = routeResultCache.get(cacheKey);
|
|
1942
1986
|
if (cachedResult) {
|
|
1943
|
-
if (
|
|
1944
|
-
cachedResult.expires <= Date.now() ||
|
|
1945
|
-
!isAcceptableIntentResult(cachedResult.result, intent) ||
|
|
1946
|
-
!isCachedSkillRelevantForIntent(cachedResult.skill, intent, context?.url)
|
|
1947
|
-
) {
|
|
1987
|
+
if (!shouldReuseRouteResultSnapshot(cachedResult, intent, context?.url)) {
|
|
1948
1988
|
routeResultCache.delete(cacheKey);
|
|
1949
1989
|
} else {
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1990
|
+
timing.cache_hit = true;
|
|
1991
|
+
writeDebugTrace("resolve", {
|
|
1992
|
+
...decisionTrace,
|
|
1993
|
+
outcome: "route_result_cache_hit",
|
|
1994
|
+
source: "route-cache",
|
|
1995
|
+
skill_id: cachedResult.skill.skill_id,
|
|
1996
|
+
selected_endpoint_id: cachedResult.endpointId ?? cachedResult.trace.endpoint_id,
|
|
1997
|
+
});
|
|
1998
|
+
return buildCachedResultResponse(
|
|
1999
|
+
cachedResult,
|
|
2000
|
+
"marketplace",
|
|
2001
|
+
finalize(
|
|
2002
|
+
"route-cache",
|
|
2003
|
+
cachedResult.result,
|
|
2004
|
+
cachedResult.skill.skill_id,
|
|
2005
|
+
cachedResult.skill,
|
|
2006
|
+
cachedResult.trace,
|
|
2007
|
+
),
|
|
2008
|
+
);
|
|
1959
2009
|
}
|
|
1960
2010
|
}
|
|
1961
2011
|
}
|