unbrowse 9.0.2 → 9.0.4
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/runtime/cli.js +121 -2
- package/runtime/mcp.js +249 -4
- package/vendor/kuri/darwin-arm64/libkuri_ffi.dylib +0 -0
- package/vendor/kuri/darwin-x64/libkuri_ffi.dylib +0 -0
- package/vendor/kuri/linux-arm64/libkuri_ffi.so +0 -0
- package/vendor/kuri/linux-x64/kuri +0 -0
- package/vendor/kuri/linux-x64/libkuri_ffi.so +0 -0
- package/vendor/kuri/manifest.json +7 -7
- package/vendor/kuri/win-x64/kuri.exe +0 -0
package/package.json
CHANGED
package/runtime/cli.js
CHANGED
|
@@ -177653,6 +177653,59 @@ function writeSkillSnapshot(cacheKey2, skill) {
|
|
|
177653
177653
|
return;
|
|
177654
177654
|
}
|
|
177655
177655
|
}
|
|
177656
|
+
function compositeSnapshotDir() {
|
|
177657
|
+
return process.env.UNBROWSE_COMPOSITE_DIR ?? join45(process.env.HOME ?? "/tmp", ".unbrowse", "composites");
|
|
177658
|
+
}
|
|
177659
|
+
function compositeAddress(domain, target, steps, edges) {
|
|
177660
|
+
const canonical2 = [
|
|
177661
|
+
`domain:${domain}`,
|
|
177662
|
+
`target:${target}`,
|
|
177663
|
+
`steps:${steps.map((s) => s.endpoint_id).join(">")}`,
|
|
177664
|
+
`edges:${edges.map((e) => `${e.from}.${e.binding}->${e.to}`).sort().join("|")}`
|
|
177665
|
+
].join("::");
|
|
177666
|
+
return `composite:${createHash35("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
177667
|
+
}
|
|
177668
|
+
function compositeLookupKey(domain, target) {
|
|
177669
|
+
const canonical2 = `domain:${domain}::target:${target}`;
|
|
177670
|
+
return `lookup:${createHash35("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
177671
|
+
}
|
|
177672
|
+
function compositeFilePath(lookupKey2) {
|
|
177673
|
+
return join45(compositeSnapshotDir(), `${lookupKey2.replace(/[^a-z0-9]/gi, "_")}.json`);
|
|
177674
|
+
}
|
|
177675
|
+
function writeComposite(c) {
|
|
177676
|
+
if (process.env.UNBROWSE_STATELESS === "1")
|
|
177677
|
+
return;
|
|
177678
|
+
if (process.env.UNBROWSE_LOCAL_CACHES !== "1")
|
|
177679
|
+
return;
|
|
177680
|
+
try {
|
|
177681
|
+
mkdirSync21(compositeSnapshotDir(), { recursive: true });
|
|
177682
|
+
const target = compositeFilePath(compositeLookupKey(c.domain, c.target));
|
|
177683
|
+
writeFileSync18(target, JSON.stringify(c), "utf-8");
|
|
177684
|
+
return target;
|
|
177685
|
+
} catch {
|
|
177686
|
+
return;
|
|
177687
|
+
}
|
|
177688
|
+
}
|
|
177689
|
+
function readComposite(domain, target) {
|
|
177690
|
+
try {
|
|
177691
|
+
const path17 = compositeFilePath(compositeLookupKey(domain, target));
|
|
177692
|
+
if (!existsSync38(path17))
|
|
177693
|
+
return;
|
|
177694
|
+
return JSON.parse(readFileSync26(path17, "utf-8"));
|
|
177695
|
+
} catch {
|
|
177696
|
+
return;
|
|
177697
|
+
}
|
|
177698
|
+
}
|
|
177699
|
+
function findCompositeInSkill(skill, target) {
|
|
177700
|
+
return skill?.composites?.find((c) => c.target === target && c.steps.length > 0);
|
|
177701
|
+
}
|
|
177702
|
+
function attachCompositeToSkill(skill, composite) {
|
|
177703
|
+
const list = skill.composites ?? (skill.composites = []);
|
|
177704
|
+
if (list.some((c) => c.composite_id === composite.composite_id))
|
|
177705
|
+
return false;
|
|
177706
|
+
list.push(composite);
|
|
177707
|
+
return true;
|
|
177708
|
+
}
|
|
177656
177709
|
function hasSearchBindings(endpoint) {
|
|
177657
177710
|
const haystack = JSON.stringify({
|
|
177658
177711
|
url: endpoint.url_template,
|
|
@@ -178715,6 +178768,21 @@ function buildCompositeEdges(target, steps, boundKeys) {
|
|
|
178715
178768
|
return from ? { from: from.endpoint_id, binding, to: target } : null;
|
|
178716
178769
|
}).filter((e) => e !== null);
|
|
178717
178770
|
}
|
|
178771
|
+
function planPrereqOrder(livePrereqOrder, persisted, isReplayable) {
|
|
178772
|
+
if (persisted && persisted.steps.length > 0) {
|
|
178773
|
+
const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
|
|
178774
|
+
if (recordedOrder.every((id) => isReplayable(id))) {
|
|
178775
|
+
return {
|
|
178776
|
+
prereqOrder: [
|
|
178777
|
+
...recordedOrder,
|
|
178778
|
+
...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
|
|
178779
|
+
],
|
|
178780
|
+
replayedCompositeId: persisted.composite_id
|
|
178781
|
+
};
|
|
178782
|
+
}
|
|
178783
|
+
}
|
|
178784
|
+
return { prereqOrder: livePrereqOrder };
|
|
178785
|
+
}
|
|
178718
178786
|
async function walkPrerequisiteChain(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
|
|
178719
178787
|
const resolved = {};
|
|
178720
178788
|
const executed = new Map;
|
|
@@ -179995,18 +180063,69 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
|
|
|
179995
180063
|
};
|
|
179996
180064
|
const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
|
|
179997
180065
|
let chainBound = {};
|
|
179998
|
-
|
|
180066
|
+
let prereqOrder = dagPlan?.prerequisite_order ?? [];
|
|
180067
|
+
let replayedCompositeId;
|
|
180068
|
+
if (stillUnbound.length > 0) {
|
|
180069
|
+
const replayDomain = skill.domain ?? (() => {
|
|
180070
|
+
try {
|
|
180071
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
180072
|
+
} catch {
|
|
180073
|
+
return "";
|
|
180074
|
+
}
|
|
180075
|
+
})();
|
|
180076
|
+
const persisted = findCompositeInSkill(skill, candidate.endpoint.endpoint_id) ?? readComposite(replayDomain, candidate.endpoint.endpoint_id);
|
|
180077
|
+
const decision = planPrereqOrder(prereqOrder, persisted, (id) => {
|
|
180078
|
+
const ep = skill.endpoints.find((e) => e.endpoint_id === id);
|
|
180079
|
+
return ep != null && canAutoExecuteEndpoint(ep);
|
|
180080
|
+
});
|
|
180081
|
+
prereqOrder = decision.prereqOrder;
|
|
180082
|
+
replayedCompositeId = decision.replayedCompositeId;
|
|
180083
|
+
if (replayedCompositeId) {
|
|
180084
|
+
console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
|
|
180085
|
+
}
|
|
180086
|
+
}
|
|
179999
180087
|
if (stillUnbound.length > 0 && prereqOrder.length > 0) {
|
|
180000
180088
|
const chainSteps = [];
|
|
180001
180089
|
chainBound = await walkPrerequisiteChain(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
|
|
180002
180090
|
if (chainSteps.length > 0) {
|
|
180091
|
+
const compositeEdges = buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
|
|
180092
|
+
const compositeDomain = skill.domain ?? (() => {
|
|
180093
|
+
try {
|
|
180094
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
180095
|
+
} catch {
|
|
180096
|
+
return "";
|
|
180097
|
+
}
|
|
180098
|
+
})();
|
|
180099
|
+
const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
|
|
180100
|
+
const compositeId = compositeAddress(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
|
|
180003
180101
|
const composite = {
|
|
180102
|
+
composite_id: compositeId,
|
|
180004
180103
|
target: candidate.endpoint.endpoint_id,
|
|
180005
180104
|
steps: chainSteps,
|
|
180006
|
-
edges:
|
|
180105
|
+
edges: compositeEdges,
|
|
180106
|
+
mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
|
|
180007
180107
|
};
|
|
180008
180108
|
decisionTrace.prerequisite_chain = chainSteps;
|
|
180009
180109
|
decisionTrace.composite = composite;
|
|
180110
|
+
if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
|
|
180111
|
+
const descriptor = {
|
|
180112
|
+
composite_id: compositeId,
|
|
180113
|
+
intent_signature: compositeIntentSig,
|
|
180114
|
+
domain: compositeDomain,
|
|
180115
|
+
target: composite.target,
|
|
180116
|
+
steps: chainSteps,
|
|
180117
|
+
edges: compositeEdges,
|
|
180118
|
+
created_at: new Date().toISOString()
|
|
180119
|
+
};
|
|
180120
|
+
const composedNewlyAttached = attachCompositeToSkill(skill, descriptor);
|
|
180121
|
+
if (composedNewlyAttached && skill.skill_id) {
|
|
180122
|
+
queuePassiveSkillPublish(skill).catch(() => {});
|
|
180123
|
+
}
|
|
180124
|
+
const persistedPath = writeComposite(descriptor);
|
|
180125
|
+
if (persistedPath) {
|
|
180126
|
+
decisionTrace.composite_persisted = compositeId;
|
|
180127
|
+
}
|
|
180128
|
+
}
|
|
180010
180129
|
console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
|
|
180011
180130
|
}
|
|
180012
180131
|
}
|
package/runtime/mcp.js
CHANGED
|
@@ -124931,6 +124931,59 @@ function writeSkillSnapshot(cacheKey2, skill) {
|
|
|
124931
124931
|
return;
|
|
124932
124932
|
}
|
|
124933
124933
|
}
|
|
124934
|
+
function compositeSnapshotDir() {
|
|
124935
|
+
return process.env.UNBROWSE_COMPOSITE_DIR ?? join26(process.env.HOME ?? "/tmp", ".unbrowse", "composites");
|
|
124936
|
+
}
|
|
124937
|
+
function compositeAddress(domain, target, steps, edges) {
|
|
124938
|
+
const canonical2 = [
|
|
124939
|
+
`domain:${domain}`,
|
|
124940
|
+
`target:${target}`,
|
|
124941
|
+
`steps:${steps.map((s) => s.endpoint_id).join(">")}`,
|
|
124942
|
+
`edges:${edges.map((e) => `${e.from}.${e.binding}->${e.to}`).sort().join("|")}`
|
|
124943
|
+
].join("::");
|
|
124944
|
+
return `composite:${createHash9("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
124945
|
+
}
|
|
124946
|
+
function compositeLookupKey(domain, target) {
|
|
124947
|
+
const canonical2 = `domain:${domain}::target:${target}`;
|
|
124948
|
+
return `lookup:${createHash9("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
124949
|
+
}
|
|
124950
|
+
function compositeFilePath(lookupKey) {
|
|
124951
|
+
return join26(compositeSnapshotDir(), `${lookupKey.replace(/[^a-z0-9]/gi, "_")}.json`);
|
|
124952
|
+
}
|
|
124953
|
+
function writeComposite(c) {
|
|
124954
|
+
if (process.env.UNBROWSE_STATELESS === "1")
|
|
124955
|
+
return;
|
|
124956
|
+
if (process.env.UNBROWSE_LOCAL_CACHES !== "1")
|
|
124957
|
+
return;
|
|
124958
|
+
try {
|
|
124959
|
+
mkdirSync15(compositeSnapshotDir(), { recursive: true });
|
|
124960
|
+
const target = compositeFilePath(compositeLookupKey(c.domain, c.target));
|
|
124961
|
+
writeFileSync13(target, JSON.stringify(c), "utf-8");
|
|
124962
|
+
return target;
|
|
124963
|
+
} catch {
|
|
124964
|
+
return;
|
|
124965
|
+
}
|
|
124966
|
+
}
|
|
124967
|
+
function readComposite(domain, target) {
|
|
124968
|
+
try {
|
|
124969
|
+
const path8 = compositeFilePath(compositeLookupKey(domain, target));
|
|
124970
|
+
if (!existsSync23(path8))
|
|
124971
|
+
return;
|
|
124972
|
+
return JSON.parse(readFileSync18(path8, "utf-8"));
|
|
124973
|
+
} catch {
|
|
124974
|
+
return;
|
|
124975
|
+
}
|
|
124976
|
+
}
|
|
124977
|
+
function findCompositeInSkill(skill, target) {
|
|
124978
|
+
return skill?.composites?.find((c) => c.target === target && c.steps.length > 0);
|
|
124979
|
+
}
|
|
124980
|
+
function attachCompositeToSkill(skill, composite) {
|
|
124981
|
+
const list = skill.composites ?? (skill.composites = []);
|
|
124982
|
+
if (list.some((c) => c.composite_id === composite.composite_id))
|
|
124983
|
+
return false;
|
|
124984
|
+
list.push(composite);
|
|
124985
|
+
return true;
|
|
124986
|
+
}
|
|
124934
124987
|
function hasSearchBindings(endpoint) {
|
|
124935
124988
|
const haystack = JSON.stringify({
|
|
124936
124989
|
url: endpoint.url_template,
|
|
@@ -125993,6 +126046,21 @@ function buildCompositeEdges(target, steps, boundKeys) {
|
|
|
125993
126046
|
return from ? { from: from.endpoint_id, binding, to: target } : null;
|
|
125994
126047
|
}).filter((e) => e !== null);
|
|
125995
126048
|
}
|
|
126049
|
+
function planPrereqOrder(livePrereqOrder, persisted, isReplayable) {
|
|
126050
|
+
if (persisted && persisted.steps.length > 0) {
|
|
126051
|
+
const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
|
|
126052
|
+
if (recordedOrder.every((id) => isReplayable(id))) {
|
|
126053
|
+
return {
|
|
126054
|
+
prereqOrder: [
|
|
126055
|
+
...recordedOrder,
|
|
126056
|
+
...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
|
|
126057
|
+
],
|
|
126058
|
+
replayedCompositeId: persisted.composite_id
|
|
126059
|
+
};
|
|
126060
|
+
}
|
|
126061
|
+
}
|
|
126062
|
+
return { prereqOrder: livePrereqOrder };
|
|
126063
|
+
}
|
|
125996
126064
|
async function walkPrerequisiteChain(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
|
|
125997
126065
|
const resolved = {};
|
|
125998
126066
|
const executed = new Map;
|
|
@@ -127273,18 +127341,69 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
|
|
|
127273
127341
|
};
|
|
127274
127342
|
const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
|
|
127275
127343
|
let chainBound = {};
|
|
127276
|
-
|
|
127344
|
+
let prereqOrder = dagPlan?.prerequisite_order ?? [];
|
|
127345
|
+
let replayedCompositeId;
|
|
127346
|
+
if (stillUnbound.length > 0) {
|
|
127347
|
+
const replayDomain = skill.domain ?? (() => {
|
|
127348
|
+
try {
|
|
127349
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
127350
|
+
} catch {
|
|
127351
|
+
return "";
|
|
127352
|
+
}
|
|
127353
|
+
})();
|
|
127354
|
+
const persisted = findCompositeInSkill(skill, candidate.endpoint.endpoint_id) ?? readComposite(replayDomain, candidate.endpoint.endpoint_id);
|
|
127355
|
+
const decision = planPrereqOrder(prereqOrder, persisted, (id) => {
|
|
127356
|
+
const ep = skill.endpoints.find((e) => e.endpoint_id === id);
|
|
127357
|
+
return ep != null && canAutoExecuteEndpoint(ep);
|
|
127358
|
+
});
|
|
127359
|
+
prereqOrder = decision.prereqOrder;
|
|
127360
|
+
replayedCompositeId = decision.replayedCompositeId;
|
|
127361
|
+
if (replayedCompositeId) {
|
|
127362
|
+
console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
|
|
127363
|
+
}
|
|
127364
|
+
}
|
|
127277
127365
|
if (stillUnbound.length > 0 && prereqOrder.length > 0) {
|
|
127278
127366
|
const chainSteps = [];
|
|
127279
127367
|
chainBound = await walkPrerequisiteChain(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
|
|
127280
127368
|
if (chainSteps.length > 0) {
|
|
127369
|
+
const compositeEdges = buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
|
|
127370
|
+
const compositeDomain = skill.domain ?? (() => {
|
|
127371
|
+
try {
|
|
127372
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
127373
|
+
} catch {
|
|
127374
|
+
return "";
|
|
127375
|
+
}
|
|
127376
|
+
})();
|
|
127377
|
+
const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
|
|
127378
|
+
const compositeId = compositeAddress(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
|
|
127281
127379
|
const composite = {
|
|
127380
|
+
composite_id: compositeId,
|
|
127282
127381
|
target: candidate.endpoint.endpoint_id,
|
|
127283
127382
|
steps: chainSteps,
|
|
127284
|
-
edges:
|
|
127383
|
+
edges: compositeEdges,
|
|
127384
|
+
mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
|
|
127285
127385
|
};
|
|
127286
127386
|
decisionTrace.prerequisite_chain = chainSteps;
|
|
127287
127387
|
decisionTrace.composite = composite;
|
|
127388
|
+
if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
|
|
127389
|
+
const descriptor = {
|
|
127390
|
+
composite_id: compositeId,
|
|
127391
|
+
intent_signature: compositeIntentSig,
|
|
127392
|
+
domain: compositeDomain,
|
|
127393
|
+
target: composite.target,
|
|
127394
|
+
steps: chainSteps,
|
|
127395
|
+
edges: compositeEdges,
|
|
127396
|
+
created_at: new Date().toISOString()
|
|
127397
|
+
};
|
|
127398
|
+
const composedNewlyAttached = attachCompositeToSkill(skill, descriptor);
|
|
127399
|
+
if (composedNewlyAttached && skill.skill_id) {
|
|
127400
|
+
queuePassiveSkillPublish(skill).catch(() => {});
|
|
127401
|
+
}
|
|
127402
|
+
const persistedPath = writeComposite(descriptor);
|
|
127403
|
+
if (persistedPath) {
|
|
127404
|
+
decisionTrace.composite_persisted = compositeId;
|
|
127405
|
+
}
|
|
127406
|
+
}
|
|
127288
127407
|
console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
|
|
127289
127408
|
}
|
|
127290
127409
|
}
|
|
@@ -191635,6 +191754,7 @@ var init_flex_pay2 = __esm(() => {
|
|
|
191635
191754
|
var exports_orchestrator = {};
|
|
191636
191755
|
__export(exports_orchestrator, {
|
|
191637
191756
|
writeSkillSnapshot: () => writeSkillSnapshot2,
|
|
191757
|
+
writeComposite: () => writeComposite2,
|
|
191638
191758
|
tryDirectJsonFetch: () => tryDirectJsonFetch2,
|
|
191639
191759
|
summarizeSchema: () => summarizeSchema2,
|
|
191640
191760
|
snapshotPathForCacheKey: () => snapshotPathForCacheKey2,
|
|
@@ -191648,10 +191768,12 @@ __export(exports_orchestrator, {
|
|
|
191648
191768
|
resolveEndpointTemplateBindings: () => resolveEndpointTemplateBindings2,
|
|
191649
191769
|
resolveAndExecute: () => resolveAndExecute2,
|
|
191650
191770
|
readSkillSnapshot: () => readSkillSnapshot2,
|
|
191771
|
+
readComposite: () => readComposite2,
|
|
191651
191772
|
pruneLocalCacheEntriesForSkill: () => pruneLocalCacheEntriesForSkill2,
|
|
191652
191773
|
promoteExplicitExecution: () => promoteExplicitExecution2,
|
|
191653
191774
|
probeLooksLikeFetchableHtmlDocument: () => probeLooksLikeFetchableHtmlDocument2,
|
|
191654
191775
|
probeLooksLikeDirectJsonApi: () => probeLooksLikeDirectJsonApi2,
|
|
191776
|
+
planPrereqOrder: () => planPrereqOrder2,
|
|
191655
191777
|
pickPreferredSkillSnapshot: () => pickPreferredSkillSnapshot2,
|
|
191656
191778
|
persistDomainCache: () => persistDomainCache2,
|
|
191657
191779
|
marketplaceSkillMatchesContext: () => marketplaceSkillMatchesContext2,
|
|
@@ -191664,13 +191786,17 @@ __export(exports_orchestrator, {
|
|
|
191664
191786
|
getDomainReuseKey: () => getDomainReuseKey2,
|
|
191665
191787
|
generateLocalDescription: () => generateLocalDescription2,
|
|
191666
191788
|
findEndpointInSkillHistory: () => findEndpointInSkillHistory2,
|
|
191789
|
+
findCompositeInSkill: () => findCompositeInSkill2,
|
|
191667
191790
|
extractSearchTermsFromIntent: () => extractSearchTermsFromIntent2,
|
|
191668
191791
|
extractSampleValues: () => extractSampleValues2,
|
|
191669
191792
|
extractLiteralSearchTermsFromIntent: () => extractLiteralSearchTermsFromIntent2,
|
|
191670
191793
|
domainSkillCache: () => domainSkillCache2,
|
|
191794
|
+
compositeLookupKey: () => compositeLookupKey2,
|
|
191795
|
+
compositeAddress: () => compositeAddress2,
|
|
191671
191796
|
chooseBestRouteCacheCandidate: () => chooseBestRouteCacheCandidate2,
|
|
191672
191797
|
buildResolveCacheKey: () => buildResolveCacheKey2,
|
|
191673
191798
|
buildCompositeEdges: () => buildCompositeEdges2,
|
|
191799
|
+
attachCompositeToSkill: () => attachCompositeToSkill2,
|
|
191674
191800
|
assessLocalExecutionResult: () => assessLocalExecutionResult2
|
|
191675
191801
|
});
|
|
191676
191802
|
import { existsSync as existsSync50, writeFileSync as writeFileSync26, readFileSync as readFileSync39, mkdirSync as mkdirSync30, readdirSync as readdirSync17 } from "node:fs";
|
|
@@ -191847,6 +191973,59 @@ function writeSkillSnapshot2(cacheKey2, skill) {
|
|
|
191847
191973
|
return;
|
|
191848
191974
|
}
|
|
191849
191975
|
}
|
|
191976
|
+
function compositeSnapshotDir2() {
|
|
191977
|
+
return process.env.UNBROWSE_COMPOSITE_DIR ?? join58(process.env.HOME ?? "/tmp", ".unbrowse", "composites");
|
|
191978
|
+
}
|
|
191979
|
+
function compositeAddress2(domain, target, steps, edges) {
|
|
191980
|
+
const canonical2 = [
|
|
191981
|
+
`domain:${domain}`,
|
|
191982
|
+
`target:${target}`,
|
|
191983
|
+
`steps:${steps.map((s) => s.endpoint_id).join(">")}`,
|
|
191984
|
+
`edges:${edges.map((e) => `${e.from}.${e.binding}->${e.to}`).sort().join("|")}`
|
|
191985
|
+
].join("::");
|
|
191986
|
+
return `composite:${createHash40("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
191987
|
+
}
|
|
191988
|
+
function compositeLookupKey2(domain, target) {
|
|
191989
|
+
const canonical2 = `domain:${domain}::target:${target}`;
|
|
191990
|
+
return `lookup:${createHash40("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
|
|
191991
|
+
}
|
|
191992
|
+
function compositeFilePath2(lookupKey2) {
|
|
191993
|
+
return join58(compositeSnapshotDir2(), `${lookupKey2.replace(/[^a-z0-9]/gi, "_")}.json`);
|
|
191994
|
+
}
|
|
191995
|
+
function writeComposite2(c) {
|
|
191996
|
+
if (process.env.UNBROWSE_STATELESS === "1")
|
|
191997
|
+
return;
|
|
191998
|
+
if (process.env.UNBROWSE_LOCAL_CACHES !== "1")
|
|
191999
|
+
return;
|
|
192000
|
+
try {
|
|
192001
|
+
mkdirSync30(compositeSnapshotDir2(), { recursive: true });
|
|
192002
|
+
const target = compositeFilePath2(compositeLookupKey2(c.domain, c.target));
|
|
192003
|
+
writeFileSync26(target, JSON.stringify(c), "utf-8");
|
|
192004
|
+
return target;
|
|
192005
|
+
} catch {
|
|
192006
|
+
return;
|
|
192007
|
+
}
|
|
192008
|
+
}
|
|
192009
|
+
function readComposite2(domain, target) {
|
|
192010
|
+
try {
|
|
192011
|
+
const path23 = compositeFilePath2(compositeLookupKey2(domain, target));
|
|
192012
|
+
if (!existsSync50(path23))
|
|
192013
|
+
return;
|
|
192014
|
+
return JSON.parse(readFileSync39(path23, "utf-8"));
|
|
192015
|
+
} catch {
|
|
192016
|
+
return;
|
|
192017
|
+
}
|
|
192018
|
+
}
|
|
192019
|
+
function findCompositeInSkill2(skill, target) {
|
|
192020
|
+
return skill?.composites?.find((c) => c.target === target && c.steps.length > 0);
|
|
192021
|
+
}
|
|
192022
|
+
function attachCompositeToSkill2(skill, composite) {
|
|
192023
|
+
const list = skill.composites ?? (skill.composites = []);
|
|
192024
|
+
if (list.some((c) => c.composite_id === composite.composite_id))
|
|
192025
|
+
return false;
|
|
192026
|
+
list.push(composite);
|
|
192027
|
+
return true;
|
|
192028
|
+
}
|
|
191850
192029
|
function hasSearchBindings2(endpoint) {
|
|
191851
192030
|
const haystack = JSON.stringify({
|
|
191852
192031
|
url: endpoint.url_template,
|
|
@@ -192914,6 +193093,21 @@ function buildCompositeEdges2(target, steps, boundKeys) {
|
|
|
192914
193093
|
return from ? { from: from.endpoint_id, binding, to: target } : null;
|
|
192915
193094
|
}).filter((e) => e !== null);
|
|
192916
193095
|
}
|
|
193096
|
+
function planPrereqOrder2(livePrereqOrder, persisted, isReplayable) {
|
|
193097
|
+
if (persisted && persisted.steps.length > 0) {
|
|
193098
|
+
const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
|
|
193099
|
+
if (recordedOrder.every((id) => isReplayable(id))) {
|
|
193100
|
+
return {
|
|
193101
|
+
prereqOrder: [
|
|
193102
|
+
...recordedOrder,
|
|
193103
|
+
...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
|
|
193104
|
+
],
|
|
193105
|
+
replayedCompositeId: persisted.composite_id
|
|
193106
|
+
};
|
|
193107
|
+
}
|
|
193108
|
+
}
|
|
193109
|
+
return { prereqOrder: livePrereqOrder };
|
|
193110
|
+
}
|
|
192917
193111
|
async function walkPrerequisiteChain2(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
|
|
192918
193112
|
const resolved = {};
|
|
192919
193113
|
const executed = new Map;
|
|
@@ -194194,18 +194388,69 @@ async function resolveAndExecute2(intent, params = {}, context, projection, opti
|
|
|
194194
194388
|
};
|
|
194195
194389
|
const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
|
|
194196
194390
|
let chainBound = {};
|
|
194197
|
-
|
|
194391
|
+
let prereqOrder = dagPlan?.prerequisite_order ?? [];
|
|
194392
|
+
let replayedCompositeId;
|
|
194393
|
+
if (stillUnbound.length > 0) {
|
|
194394
|
+
const replayDomain = skill.domain ?? (() => {
|
|
194395
|
+
try {
|
|
194396
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
194397
|
+
} catch {
|
|
194398
|
+
return "";
|
|
194399
|
+
}
|
|
194400
|
+
})();
|
|
194401
|
+
const persisted = findCompositeInSkill2(skill, candidate.endpoint.endpoint_id) ?? readComposite2(replayDomain, candidate.endpoint.endpoint_id);
|
|
194402
|
+
const decision = planPrereqOrder2(prereqOrder, persisted, (id) => {
|
|
194403
|
+
const ep = skill.endpoints.find((e) => e.endpoint_id === id);
|
|
194404
|
+
return ep != null && canAutoExecuteEndpoint(ep);
|
|
194405
|
+
});
|
|
194406
|
+
prereqOrder = decision.prereqOrder;
|
|
194407
|
+
replayedCompositeId = decision.replayedCompositeId;
|
|
194408
|
+
if (replayedCompositeId) {
|
|
194409
|
+
console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
|
|
194410
|
+
}
|
|
194411
|
+
}
|
|
194198
194412
|
if (stillUnbound.length > 0 && prereqOrder.length > 0) {
|
|
194199
194413
|
const chainSteps = [];
|
|
194200
194414
|
chainBound = await walkPrerequisiteChain2(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
|
|
194201
194415
|
if (chainSteps.length > 0) {
|
|
194416
|
+
const compositeEdges = buildCompositeEdges2(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
|
|
194417
|
+
const compositeDomain = skill.domain ?? (() => {
|
|
194418
|
+
try {
|
|
194419
|
+
return new URL(candidate.endpoint.url_template).hostname;
|
|
194420
|
+
} catch {
|
|
194421
|
+
return "";
|
|
194422
|
+
}
|
|
194423
|
+
})();
|
|
194424
|
+
const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
|
|
194425
|
+
const compositeId = compositeAddress2(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
|
|
194202
194426
|
const composite = {
|
|
194427
|
+
composite_id: compositeId,
|
|
194203
194428
|
target: candidate.endpoint.endpoint_id,
|
|
194204
194429
|
steps: chainSteps,
|
|
194205
|
-
edges:
|
|
194430
|
+
edges: compositeEdges,
|
|
194431
|
+
mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
|
|
194206
194432
|
};
|
|
194207
194433
|
decisionTrace.prerequisite_chain = chainSteps;
|
|
194208
194434
|
decisionTrace.composite = composite;
|
|
194435
|
+
if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
|
|
194436
|
+
const descriptor = {
|
|
194437
|
+
composite_id: compositeId,
|
|
194438
|
+
intent_signature: compositeIntentSig,
|
|
194439
|
+
domain: compositeDomain,
|
|
194440
|
+
target: composite.target,
|
|
194441
|
+
steps: chainSteps,
|
|
194442
|
+
edges: compositeEdges,
|
|
194443
|
+
created_at: new Date().toISOString()
|
|
194444
|
+
};
|
|
194445
|
+
const composedNewlyAttached = attachCompositeToSkill2(skill, descriptor);
|
|
194446
|
+
if (composedNewlyAttached && skill.skill_id) {
|
|
194447
|
+
queuePassiveSkillPublish(skill).catch(() => {});
|
|
194448
|
+
}
|
|
194449
|
+
const persistedPath = writeComposite2(descriptor);
|
|
194450
|
+
if (persistedPath) {
|
|
194451
|
+
decisionTrace.composite_persisted = compositeId;
|
|
194452
|
+
}
|
|
194453
|
+
}
|
|
194209
194454
|
console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
|
|
194210
194455
|
}
|
|
194211
194456
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"repo_url": "https://github.com/justrach/kuri.git",
|
|
3
3
|
"branch": "adding-extensions",
|
|
4
4
|
"source_sha": "8938f89f3d0c032bd19c59db0de4eadca18a1800",
|
|
5
|
-
"built_at": "2026-06-
|
|
5
|
+
"built_at": "2026-06-14T04:52:03.906Z",
|
|
6
6
|
"binaries": {
|
|
7
7
|
"darwin-arm64": {
|
|
8
8
|
"zig_target": "aarch64-macos",
|
|
@@ -21,33 +21,33 @@
|
|
|
21
21
|
},
|
|
22
22
|
"linux-x64": {
|
|
23
23
|
"zig_target": "x86_64-linux",
|
|
24
|
-
"sha256": "
|
|
24
|
+
"sha256": "473995d9a14513c1dfd3a86d29f0c10fb6f4b735565f9879574a325a4efbe617"
|
|
25
25
|
},
|
|
26
26
|
"win-x64": {
|
|
27
27
|
"zig_target": "x86_64-windows-gnu",
|
|
28
|
-
"sha256": "
|
|
28
|
+
"sha256": "5c98de92a1675ec1e1d823b2b0bd9c6ab90c4b32a8c34cdcf51c84e240a377c9"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"ffi": {
|
|
32
32
|
"darwin-arm64": {
|
|
33
33
|
"zig_target": "aarch64-macos",
|
|
34
34
|
"lib": "libkuri_ffi.dylib",
|
|
35
|
-
"sha256": "
|
|
35
|
+
"sha256": "ebf5ef3f77623b67799702029de32b5ade1dc8b758c379740998d20d2bc9d10c"
|
|
36
36
|
},
|
|
37
37
|
"darwin-x64": {
|
|
38
38
|
"zig_target": "x86_64-macos",
|
|
39
39
|
"lib": "libkuri_ffi.dylib",
|
|
40
|
-
"sha256": "
|
|
40
|
+
"sha256": "7dfdb81bab83b861245afefea9bab1a7342f646ced84e62ecdd4d9f1d6ac589c"
|
|
41
41
|
},
|
|
42
42
|
"linux-arm64": {
|
|
43
43
|
"zig_target": "aarch64-linux",
|
|
44
44
|
"lib": "libkuri_ffi.so",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "435454b86a17ca8605c7129b50f7f090ead9c4928e5337b1b833fda7f4e82403"
|
|
46
46
|
},
|
|
47
47
|
"linux-x64": {
|
|
48
48
|
"zig_target": "x86_64-linux",
|
|
49
49
|
"lib": "libkuri_ffi.so",
|
|
50
|
-
"sha256": "
|
|
50
|
+
"sha256": "3d05e8b0203d24c6d1b051381e57e883f7fcc0bda0a86d75c2b4d243fb15212b"
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
Binary file
|