unbrowse 9.0.2 → 9.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unbrowse",
3
- "version": "9.0.2",
3
+ "version": "9.0.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/unbrowse-ai/unbrowse.git"
package/runtime/cli.js CHANGED
@@ -177653,6 +177653,49 @@ 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
+ }
177656
177699
  function hasSearchBindings(endpoint) {
177657
177700
  const haystack = JSON.stringify({
177658
177701
  url: endpoint.url_template,
@@ -178715,6 +178758,21 @@ function buildCompositeEdges(target, steps, boundKeys) {
178715
178758
  return from ? { from: from.endpoint_id, binding, to: target } : null;
178716
178759
  }).filter((e) => e !== null);
178717
178760
  }
178761
+ function planPrereqOrder(livePrereqOrder, persisted, isReplayable) {
178762
+ if (persisted && persisted.steps.length > 0) {
178763
+ const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
178764
+ if (recordedOrder.every((id) => isReplayable(id))) {
178765
+ return {
178766
+ prereqOrder: [
178767
+ ...recordedOrder,
178768
+ ...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
178769
+ ],
178770
+ replayedCompositeId: persisted.composite_id
178771
+ };
178772
+ }
178773
+ }
178774
+ return { prereqOrder: livePrereqOrder };
178775
+ }
178718
178776
  async function walkPrerequisiteChain(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
178719
178777
  const resolved = {};
178720
178778
  const executed = new Map;
@@ -179995,18 +180053,64 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
179995
180053
  };
179996
180054
  const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
179997
180055
  let chainBound = {};
179998
- const prereqOrder = dagPlan?.prerequisite_order ?? [];
180056
+ let prereqOrder = dagPlan?.prerequisite_order ?? [];
180057
+ let replayedCompositeId;
180058
+ if (stillUnbound.length > 0) {
180059
+ const replayDomain = skill.domain ?? (() => {
180060
+ try {
180061
+ return new URL(candidate.endpoint.url_template).hostname;
180062
+ } catch {
180063
+ return "";
180064
+ }
180065
+ })();
180066
+ const persisted = readComposite(replayDomain, candidate.endpoint.endpoint_id);
180067
+ const decision = planPrereqOrder(prereqOrder, persisted, (id) => {
180068
+ const ep = skill.endpoints.find((e) => e.endpoint_id === id);
180069
+ return ep != null && canAutoExecuteEndpoint(ep);
180070
+ });
180071
+ prereqOrder = decision.prereqOrder;
180072
+ replayedCompositeId = decision.replayedCompositeId;
180073
+ if (replayedCompositeId) {
180074
+ console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
180075
+ }
180076
+ }
179999
180077
  if (stillUnbound.length > 0 && prereqOrder.length > 0) {
180000
180078
  const chainSteps = [];
180001
180079
  chainBound = await walkPrerequisiteChain(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
180002
180080
  if (chainSteps.length > 0) {
180081
+ const compositeEdges = buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
180082
+ const compositeDomain = skill.domain ?? (() => {
180083
+ try {
180084
+ return new URL(candidate.endpoint.url_template).hostname;
180085
+ } catch {
180086
+ return "";
180087
+ }
180088
+ })();
180089
+ const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
180090
+ const compositeId = compositeAddress(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
180003
180091
  const composite = {
180092
+ composite_id: compositeId,
180004
180093
  target: candidate.endpoint.endpoint_id,
180005
180094
  steps: chainSteps,
180006
- edges: buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound))
180095
+ edges: compositeEdges,
180096
+ mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
180007
180097
  };
180008
180098
  decisionTrace.prerequisite_chain = chainSteps;
180009
180099
  decisionTrace.composite = composite;
180100
+ if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
180101
+ const persistedPath = writeComposite({
180102
+ composite_id: compositeId,
180103
+ intent_signature: compositeIntentSig,
180104
+ domain: compositeDomain,
180105
+ target: composite.target,
180106
+ steps: chainSteps,
180107
+ edges: compositeEdges,
180108
+ created_at: new Date().toISOString()
180109
+ });
180110
+ if (persistedPath) {
180111
+ decisionTrace.composite_persisted = compositeId;
180112
+ }
180113
+ }
180010
180114
  console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
180011
180115
  }
180012
180116
  }
package/runtime/mcp.js CHANGED
@@ -124931,6 +124931,49 @@ 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
+ }
124934
124977
  function hasSearchBindings(endpoint) {
124935
124978
  const haystack = JSON.stringify({
124936
124979
  url: endpoint.url_template,
@@ -125993,6 +126036,21 @@ function buildCompositeEdges(target, steps, boundKeys) {
125993
126036
  return from ? { from: from.endpoint_id, binding, to: target } : null;
125994
126037
  }).filter((e) => e !== null);
125995
126038
  }
126039
+ function planPrereqOrder(livePrereqOrder, persisted, isReplayable) {
126040
+ if (persisted && persisted.steps.length > 0) {
126041
+ const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
126042
+ if (recordedOrder.every((id) => isReplayable(id))) {
126043
+ return {
126044
+ prereqOrder: [
126045
+ ...recordedOrder,
126046
+ ...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
126047
+ ],
126048
+ replayedCompositeId: persisted.composite_id
126049
+ };
126050
+ }
126051
+ }
126052
+ return { prereqOrder: livePrereqOrder };
126053
+ }
125996
126054
  async function walkPrerequisiteChain(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
125997
126055
  const resolved = {};
125998
126056
  const executed = new Map;
@@ -127273,18 +127331,64 @@ async function resolveAndExecute(intent, params = {}, context, projection, optio
127273
127331
  };
127274
127332
  const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
127275
127333
  let chainBound = {};
127276
- const prereqOrder = dagPlan?.prerequisite_order ?? [];
127334
+ let prereqOrder = dagPlan?.prerequisite_order ?? [];
127335
+ let replayedCompositeId;
127336
+ if (stillUnbound.length > 0) {
127337
+ const replayDomain = skill.domain ?? (() => {
127338
+ try {
127339
+ return new URL(candidate.endpoint.url_template).hostname;
127340
+ } catch {
127341
+ return "";
127342
+ }
127343
+ })();
127344
+ const persisted = readComposite(replayDomain, candidate.endpoint.endpoint_id);
127345
+ const decision = planPrereqOrder(prereqOrder, persisted, (id) => {
127346
+ const ep = skill.endpoints.find((e) => e.endpoint_id === id);
127347
+ return ep != null && canAutoExecuteEndpoint(ep);
127348
+ });
127349
+ prereqOrder = decision.prereqOrder;
127350
+ replayedCompositeId = decision.replayedCompositeId;
127351
+ if (replayedCompositeId) {
127352
+ console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
127353
+ }
127354
+ }
127277
127355
  if (stillUnbound.length > 0 && prereqOrder.length > 0) {
127278
127356
  const chainSteps = [];
127279
127357
  chainBound = await walkPrerequisiteChain(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
127280
127358
  if (chainSteps.length > 0) {
127359
+ const compositeEdges = buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
127360
+ const compositeDomain = skill.domain ?? (() => {
127361
+ try {
127362
+ return new URL(candidate.endpoint.url_template).hostname;
127363
+ } catch {
127364
+ return "";
127365
+ }
127366
+ })();
127367
+ const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
127368
+ const compositeId = compositeAddress(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
127281
127369
  const composite = {
127370
+ composite_id: compositeId,
127282
127371
  target: candidate.endpoint.endpoint_id,
127283
127372
  steps: chainSteps,
127284
- edges: buildCompositeEdges(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound))
127373
+ edges: compositeEdges,
127374
+ mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
127285
127375
  };
127286
127376
  decisionTrace.prerequisite_chain = chainSteps;
127287
127377
  decisionTrace.composite = composite;
127378
+ if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
127379
+ const persistedPath = writeComposite({
127380
+ composite_id: compositeId,
127381
+ intent_signature: compositeIntentSig,
127382
+ domain: compositeDomain,
127383
+ target: composite.target,
127384
+ steps: chainSteps,
127385
+ edges: compositeEdges,
127386
+ created_at: new Date().toISOString()
127387
+ });
127388
+ if (persistedPath) {
127389
+ decisionTrace.composite_persisted = compositeId;
127390
+ }
127391
+ }
127288
127392
  console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
127289
127393
  }
127290
127394
  }
@@ -191635,6 +191739,7 @@ var init_flex_pay2 = __esm(() => {
191635
191739
  var exports_orchestrator = {};
191636
191740
  __export(exports_orchestrator, {
191637
191741
  writeSkillSnapshot: () => writeSkillSnapshot2,
191742
+ writeComposite: () => writeComposite2,
191638
191743
  tryDirectJsonFetch: () => tryDirectJsonFetch2,
191639
191744
  summarizeSchema: () => summarizeSchema2,
191640
191745
  snapshotPathForCacheKey: () => snapshotPathForCacheKey2,
@@ -191648,10 +191753,12 @@ __export(exports_orchestrator, {
191648
191753
  resolveEndpointTemplateBindings: () => resolveEndpointTemplateBindings2,
191649
191754
  resolveAndExecute: () => resolveAndExecute2,
191650
191755
  readSkillSnapshot: () => readSkillSnapshot2,
191756
+ readComposite: () => readComposite2,
191651
191757
  pruneLocalCacheEntriesForSkill: () => pruneLocalCacheEntriesForSkill2,
191652
191758
  promoteExplicitExecution: () => promoteExplicitExecution2,
191653
191759
  probeLooksLikeFetchableHtmlDocument: () => probeLooksLikeFetchableHtmlDocument2,
191654
191760
  probeLooksLikeDirectJsonApi: () => probeLooksLikeDirectJsonApi2,
191761
+ planPrereqOrder: () => planPrereqOrder2,
191655
191762
  pickPreferredSkillSnapshot: () => pickPreferredSkillSnapshot2,
191656
191763
  persistDomainCache: () => persistDomainCache2,
191657
191764
  marketplaceSkillMatchesContext: () => marketplaceSkillMatchesContext2,
@@ -191668,6 +191775,8 @@ __export(exports_orchestrator, {
191668
191775
  extractSampleValues: () => extractSampleValues2,
191669
191776
  extractLiteralSearchTermsFromIntent: () => extractLiteralSearchTermsFromIntent2,
191670
191777
  domainSkillCache: () => domainSkillCache2,
191778
+ compositeLookupKey: () => compositeLookupKey2,
191779
+ compositeAddress: () => compositeAddress2,
191671
191780
  chooseBestRouteCacheCandidate: () => chooseBestRouteCacheCandidate2,
191672
191781
  buildResolveCacheKey: () => buildResolveCacheKey2,
191673
191782
  buildCompositeEdges: () => buildCompositeEdges2,
@@ -191847,6 +191956,49 @@ function writeSkillSnapshot2(cacheKey2, skill) {
191847
191956
  return;
191848
191957
  }
191849
191958
  }
191959
+ function compositeSnapshotDir2() {
191960
+ return process.env.UNBROWSE_COMPOSITE_DIR ?? join58(process.env.HOME ?? "/tmp", ".unbrowse", "composites");
191961
+ }
191962
+ function compositeAddress2(domain, target, steps, edges) {
191963
+ const canonical2 = [
191964
+ `domain:${domain}`,
191965
+ `target:${target}`,
191966
+ `steps:${steps.map((s) => s.endpoint_id).join(">")}`,
191967
+ `edges:${edges.map((e) => `${e.from}.${e.binding}->${e.to}`).sort().join("|")}`
191968
+ ].join("::");
191969
+ return `composite:${createHash40("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
191970
+ }
191971
+ function compositeLookupKey2(domain, target) {
191972
+ const canonical2 = `domain:${domain}::target:${target}`;
191973
+ return `lookup:${createHash40("sha256").update(canonical2).digest("hex").slice(0, 32)}`;
191974
+ }
191975
+ function compositeFilePath2(lookupKey2) {
191976
+ return join58(compositeSnapshotDir2(), `${lookupKey2.replace(/[^a-z0-9]/gi, "_")}.json`);
191977
+ }
191978
+ function writeComposite2(c) {
191979
+ if (process.env.UNBROWSE_STATELESS === "1")
191980
+ return;
191981
+ if (process.env.UNBROWSE_LOCAL_CACHES !== "1")
191982
+ return;
191983
+ try {
191984
+ mkdirSync30(compositeSnapshotDir2(), { recursive: true });
191985
+ const target = compositeFilePath2(compositeLookupKey2(c.domain, c.target));
191986
+ writeFileSync26(target, JSON.stringify(c), "utf-8");
191987
+ return target;
191988
+ } catch {
191989
+ return;
191990
+ }
191991
+ }
191992
+ function readComposite2(domain, target) {
191993
+ try {
191994
+ const path23 = compositeFilePath2(compositeLookupKey2(domain, target));
191995
+ if (!existsSync50(path23))
191996
+ return;
191997
+ return JSON.parse(readFileSync39(path23, "utf-8"));
191998
+ } catch {
191999
+ return;
192000
+ }
192001
+ }
191850
192002
  function hasSearchBindings2(endpoint) {
191851
192003
  const haystack = JSON.stringify({
191852
192004
  url: endpoint.url_template,
@@ -192914,6 +193066,21 @@ function buildCompositeEdges2(target, steps, boundKeys) {
192914
193066
  return from ? { from: from.endpoint_id, binding, to: target } : null;
192915
193067
  }).filter((e) => e !== null);
192916
193068
  }
193069
+ function planPrereqOrder2(livePrereqOrder, persisted, isReplayable) {
193070
+ if (persisted && persisted.steps.length > 0) {
193071
+ const recordedOrder = persisted.steps.map((s) => s.endpoint_id);
193072
+ if (recordedOrder.every((id) => isReplayable(id))) {
193073
+ return {
193074
+ prereqOrder: [
193075
+ ...recordedOrder,
193076
+ ...livePrereqOrder.filter((p) => !recordedOrder.includes(p))
193077
+ ],
193078
+ replayedCompositeId: persisted.composite_id
193079
+ };
193080
+ }
193081
+ }
193082
+ return { prereqOrder: livePrereqOrder };
193083
+ }
192917
193084
  async function walkPrerequisiteChain2(skill, unboundParams, prerequisiteOrder, baseParams, queryIntent, projection, options, steps) {
192918
193085
  const resolved = {};
192919
193086
  const executed = new Map;
@@ -194194,18 +194361,64 @@ async function resolveAndExecute2(intent, params = {}, context, projection, opti
194194
194361
  };
194195
194362
  const stillUnbound = [...candidate.endpoint.url_template.matchAll(/\{([^}]+)\}/g)].map((m) => m[1]).filter((name) => allBound[name] == null || allBound[name] === "");
194196
194363
  let chainBound = {};
194197
- const prereqOrder = dagPlan?.prerequisite_order ?? [];
194364
+ let prereqOrder = dagPlan?.prerequisite_order ?? [];
194365
+ let replayedCompositeId;
194366
+ if (stillUnbound.length > 0) {
194367
+ const replayDomain = skill.domain ?? (() => {
194368
+ try {
194369
+ return new URL(candidate.endpoint.url_template).hostname;
194370
+ } catch {
194371
+ return "";
194372
+ }
194373
+ })();
194374
+ const persisted = readComposite2(replayDomain, candidate.endpoint.endpoint_id);
194375
+ const decision = planPrereqOrder2(prereqOrder, persisted, (id) => {
194376
+ const ep = skill.endpoints.find((e) => e.endpoint_id === id);
194377
+ return ep != null && canAutoExecuteEndpoint(ep);
194378
+ });
194379
+ prereqOrder = decision.prereqOrder;
194380
+ replayedCompositeId = decision.replayedCompositeId;
194381
+ if (replayedCompositeId) {
194382
+ console.log(`[chain] composite replay → ${candidate.endpoint.endpoint_id} (${replayedCompositeId})`);
194383
+ }
194384
+ }
194198
194385
  if (stillUnbound.length > 0 && prereqOrder.length > 0) {
194199
194386
  const chainSteps = [];
194200
194387
  chainBound = await walkPrerequisiteChain2(skill, stillUnbound, prereqOrder, { ...templateDefaults, ...endpointParams, ...syncInferred, ...searchOverrides }, queryIntent, projection, { ...options, intent: queryIntent, contextUrl: context?.url }, chainSteps);
194201
194388
  if (chainSteps.length > 0) {
194389
+ const compositeEdges = buildCompositeEdges2(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound));
194390
+ const compositeDomain = skill.domain ?? (() => {
194391
+ try {
194392
+ return new URL(candidate.endpoint.url_template).hostname;
194393
+ } catch {
194394
+ return "";
194395
+ }
194396
+ })();
194397
+ const compositeIntentSig = (queryIntent ?? "").trim().toLowerCase();
194398
+ const compositeId = compositeAddress2(compositeDomain, candidate.endpoint.endpoint_id, chainSteps, compositeEdges);
194202
194399
  const composite = {
194400
+ composite_id: compositeId,
194203
194401
  target: candidate.endpoint.endpoint_id,
194204
194402
  steps: chainSteps,
194205
- edges: buildCompositeEdges2(candidate.endpoint.endpoint_id, chainSteps, Object.keys(chainBound))
194403
+ edges: compositeEdges,
194404
+ mode: replayedCompositeId === compositeId ? "composite_replay" : "composite_walk"
194206
194405
  };
194207
194406
  decisionTrace.prerequisite_chain = chainSteps;
194208
194407
  decisionTrace.composite = composite;
194408
+ if (chainSteps.every((s) => s.ok) && canAutoExecuteEndpoint(candidate.endpoint)) {
194409
+ const persistedPath = writeComposite2({
194410
+ composite_id: compositeId,
194411
+ intent_signature: compositeIntentSig,
194412
+ domain: compositeDomain,
194413
+ target: composite.target,
194414
+ steps: chainSteps,
194415
+ edges: compositeEdges,
194416
+ created_at: new Date().toISOString()
194417
+ });
194418
+ if (persistedPath) {
194419
+ decisionTrace.composite_persisted = compositeId;
194420
+ }
194421
+ }
194209
194422
  console.log(`[chain] composite → ${composite.target} via ` + composite.edges.map((e) => `${e.from}.${e.binding}`).join(" + ") || "(no edges)");
194210
194423
  }
194211
194424
  }
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-14T02:28:58.704Z",
5
+ "built_at": "2026-06-14T04:09:29.728Z",
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": "258ae9db1a86d21d39e248904135693f3e20ce2fa4b32e3be48c4b32ebc9989e"
24
+ "sha256": "287c37dd7c9409214b638ba588e26d160fd5078d7b50c0e8673eec64086692c1"
25
25
  },
26
26
  "win-x64": {
27
27
  "zig_target": "x86_64-windows-gnu",
28
- "sha256": "d1a16044a5425e8e2b038af4c8d052021857829d8f08e30eccfbbe5ca62989c1"
28
+ "sha256": "12374edb4547931d6efe8c187dc91c92984f0305fe7cc32276a9a7eddda17808"
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": "b059e6b94010942376c7c6de683b84b937477413a8a77b826700f235826b5634"
35
+ "sha256": "e4d25d11504e9f366ff4fca192dd5bfc7d3475a483157541816ff6b75329b498"
36
36
  },
37
37
  "darwin-x64": {
38
38
  "zig_target": "x86_64-macos",
39
39
  "lib": "libkuri_ffi.dylib",
40
- "sha256": "de9856b3350bc26ecd8e4c167b46361bad9e5f775b61a637970bce38e596da1d"
40
+ "sha256": "c3858a4d4d9f2a713c19835c3f2de15687aaadb6a8f091455920708eda84d069"
41
41
  },
42
42
  "linux-arm64": {
43
43
  "zig_target": "aarch64-linux",
44
44
  "lib": "libkuri_ffi.so",
45
- "sha256": "e088ff534085f03cd4f79629bd7ffc2a4731aaabb4f28200edb1d55d873a29ad"
45
+ "sha256": "21418a3144796ddcec50721f6a2a6ee86c9518e4515cfdd45a644ee026bc4433"
46
46
  },
47
47
  "linux-x64": {
48
48
  "zig_target": "x86_64-linux",
49
49
  "lib": "libkuri_ffi.so",
50
- "sha256": "1250b2a48a181a15abf7019cd66d6e136ff13c89dd56e205bd5b0c740ed06f16"
50
+ "sha256": "58c61c8bcaaa9d49e78077732d5e4493cad9d684853eb6f501da810d5d3550a4"
51
51
  }
52
52
  }
53
53
  }
Binary file