@solana-agent-wallet-adapter/cli 0.1.0 → 0.2.0

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/index.js CHANGED
@@ -6837,7 +6837,7 @@ var require_utils2 = __commonJS({
6837
6837
  exports.u32 = u323;
6838
6838
  exports.clean = clean3;
6839
6839
  exports.createView = createView3;
6840
- exports.rotr = rotr2;
6840
+ exports.rotr = rotr3;
6841
6841
  exports.rotl = rotl2;
6842
6842
  exports.byteSwap = byteSwap2;
6843
6843
  exports.byteSwap32 = byteSwap322;
@@ -6901,7 +6901,7 @@ var require_utils2 = __commonJS({
6901
6901
  function createView3(arr) {
6902
6902
  return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
6903
6903
  }
6904
- function rotr2(word, shift) {
6904
+ function rotr3(word, shift) {
6905
6905
  return word << 32 - shift | word >>> shift;
6906
6906
  }
6907
6907
  function rotl2(word, shift) {
@@ -7346,7 +7346,7 @@ var require_sha2 = __commonJS({
7346
7346
  var _md_ts_1 = require_md();
7347
7347
  var u64 = require_u64();
7348
7348
  var utils_ts_1 = require_utils2();
7349
- var SHA256_K2 = /* @__PURE__ */ Uint32Array.from([
7349
+ var SHA256_K3 = /* @__PURE__ */ Uint32Array.from([
7350
7350
  1116352408,
7351
7351
  1899447441,
7352
7352
  3049323471,
@@ -7453,7 +7453,7 @@ var require_sha2 = __commonJS({
7453
7453
  let { A: A4, B: B3, C: C2, D: D3, E: E3, F: F3, G: G3, H: H5 } = this;
7454
7454
  for (let i = 0; i < 64; i++) {
7455
7455
  const sigma1 = (0, utils_ts_1.rotr)(E3, 6) ^ (0, utils_ts_1.rotr)(E3, 11) ^ (0, utils_ts_1.rotr)(E3, 25);
7456
- const T1 = H5 + sigma1 + (0, _md_ts_1.Chi)(E3, F3, G3) + SHA256_K2[i] + SHA256_W2[i] | 0;
7456
+ const T1 = H5 + sigma1 + (0, _md_ts_1.Chi)(E3, F3, G3) + SHA256_K3[i] + SHA256_W2[i] | 0;
7457
7457
  const sigma0 = (0, utils_ts_1.rotr)(A4, 2) ^ (0, utils_ts_1.rotr)(A4, 13) ^ (0, utils_ts_1.rotr)(A4, 22);
7458
7458
  const T22 = sigma0 + (0, _md_ts_1.Maj)(A4, B3, C2) | 0;
7459
7459
  H5 = G3;
@@ -17286,7 +17286,7 @@ var require_dist2 = __commonJS({
17286
17286
  function isNonArrayObject(x4) {
17287
17287
  return isObject2(x4) && !Array.isArray(x4);
17288
17288
  }
17289
- function isPlainObject3(x4) {
17289
+ function isPlainObject4(x4) {
17290
17290
  if (Object.prototype.toString.call(x4) !== "[object Object]") {
17291
17291
  return false;
17292
17292
  }
@@ -17926,7 +17926,7 @@ var require_dist2 = __commonJS({
17926
17926
  if (x4 === void 0) {
17927
17927
  return f;
17928
17928
  }
17929
- if (!options.strict && isPlainObject3(x4) && isPlainObject3(f)) {
17929
+ if (!options.strict && isPlainObject4(x4) && isPlainObject4(f)) {
17930
17930
  const ret = { ...x4 };
17931
17931
  let changed = false;
17932
17932
  for (const key in f) {
@@ -63624,6 +63624,901 @@ function sleep(ms) {
63624
63624
  // ../mcp-server/dist/actionService.js
63625
63625
  var import_web3 = __toESM(require_index_cjs(), 1);
63626
63626
 
63627
+ // ../workflow/dist/cadence.js
63628
+ function exhaustionReason(schedule, now) {
63629
+ if (schedule.maxOccurrences !== void 0 && (schedule.occurrencesCreated ?? 0) >= schedule.maxOccurrences) {
63630
+ return "max_occurrences";
63631
+ }
63632
+ if (schedule.expiresAt) {
63633
+ const expiry = new Date(schedule.expiresAt);
63634
+ if (!Number.isNaN(expiry.getTime()) && now.getTime() >= expiry.getTime()) {
63635
+ return "expired";
63636
+ }
63637
+ }
63638
+ return null;
63639
+ }
63640
+ function nextFutureOccurrence(schedule, now) {
63641
+ const startAt = recurringStartAt(schedule);
63642
+ if (!startAt)
63643
+ return null;
63644
+ const candidate = nextFutureByCadence(schedule, now, startAt);
63645
+ if (!candidate)
63646
+ return null;
63647
+ if (schedule.expiresAt) {
63648
+ const expiry = new Date(schedule.expiresAt);
63649
+ if (!Number.isNaN(expiry.getTime()) && candidate.dueAt.getTime() >= expiry.getTime()) {
63650
+ return null;
63651
+ }
63652
+ }
63653
+ return candidate;
63654
+ }
63655
+ function latestDueOccurrence(schedule, now) {
63656
+ const startAt = recurringStartAt(schedule);
63657
+ if (!startAt)
63658
+ return null;
63659
+ const candidate = latestDueByCadence(schedule, now, startAt);
63660
+ if (!candidate || candidate.dueAt.getTime() < startAt.getTime())
63661
+ return null;
63662
+ if (schedule.expiresAt) {
63663
+ const expiry = new Date(schedule.expiresAt);
63664
+ if (!Number.isNaN(expiry.getTime()) && candidate.dueAt.getTime() >= expiry.getTime()) {
63665
+ return null;
63666
+ }
63667
+ }
63668
+ return candidate;
63669
+ }
63670
+ function previewUpcoming(schedule, now, count) {
63671
+ if (count <= 0)
63672
+ return [];
63673
+ const results = [];
63674
+ let cursorNow = now;
63675
+ let occurrencesCreated = schedule.occurrencesCreated ?? 0;
63676
+ for (let i = 0; i < count; i += 1) {
63677
+ const probe = { ...schedule, occurrencesCreated };
63678
+ if (exhaustionReason(probe, cursorNow))
63679
+ break;
63680
+ const next = nextFutureOccurrence(probe, cursorNow);
63681
+ if (!next)
63682
+ break;
63683
+ results.push(next);
63684
+ occurrencesCreated += 1;
63685
+ cursorNow = new Date(next.dueAt.getTime());
63686
+ }
63687
+ return results;
63688
+ }
63689
+ function recurringStartAt(schedule) {
63690
+ const value = new Date(schedule.startAt ?? schedule.createdAt);
63691
+ return Number.isNaN(value.getTime()) ? null : value;
63692
+ }
63693
+ function parseLocalTime(value) {
63694
+ if (!value)
63695
+ return null;
63696
+ const [hourRaw, minuteRaw] = value.split(":");
63697
+ const hour = Number(hourRaw);
63698
+ const minute = Number(minuteRaw);
63699
+ if (!Number.isInteger(hour) || !Number.isInteger(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
63700
+ return null;
63701
+ }
63702
+ return { hour, minute };
63703
+ }
63704
+ function clampedMonthlyDate(year, month, dayOfMonth, hour, minute) {
63705
+ const lastDay = new Date(year, month + 1, 0).getDate();
63706
+ return new Date(year, month, Math.min(dayOfMonth, lastDay), hour, minute, 0, 0);
63707
+ }
63708
+ function monthlyKey(date3) {
63709
+ const month = String(date3.getMonth() + 1).padStart(2, "0");
63710
+ const day = String(date3.getDate()).padStart(2, "0");
63711
+ return `${date3.getFullYear()}-${month}-${day}`;
63712
+ }
63713
+ function intervalKey(dueAt, cadence) {
63714
+ if (cadence === "interval_days")
63715
+ return monthlyKey(dueAt);
63716
+ return dueAt.toISOString();
63717
+ }
63718
+ function nextFutureByCadence(schedule, now, startAt) {
63719
+ switch (schedule.cadence) {
63720
+ case "weekly":
63721
+ return nextFutureWeekly(schedule, now, startAt);
63722
+ case "monthly":
63723
+ return nextFutureMonthly(schedule, now, startAt);
63724
+ case "interval_days":
63725
+ return nextFutureInterval(schedule, now, schedule.intervalDays, 24 * 60 * 60 * 1e3);
63726
+ case "interval_hours":
63727
+ return nextFutureInterval(schedule, now, schedule.intervalHours, 60 * 60 * 1e3);
63728
+ case "interval_minutes":
63729
+ return nextFutureInterval(schedule, now, schedule.intervalMinutes, 60 * 1e3);
63730
+ default:
63731
+ return assertNeverCadence(schedule.cadence);
63732
+ }
63733
+ }
63734
+ function latestDueByCadence(schedule, now, startAt) {
63735
+ switch (schedule.cadence) {
63736
+ case "weekly":
63737
+ return latestDueWeekly(schedule, now, startAt);
63738
+ case "monthly":
63739
+ return latestDueMonthly(schedule, now, startAt);
63740
+ case "interval_days":
63741
+ return latestDueInterval(schedule, now, schedule.intervalDays, 24 * 60 * 60 * 1e3);
63742
+ case "interval_hours":
63743
+ return latestDueInterval(schedule, now, schedule.intervalHours, 60 * 60 * 1e3);
63744
+ case "interval_minutes":
63745
+ return latestDueInterval(schedule, now, schedule.intervalMinutes, 60 * 1e3);
63746
+ default:
63747
+ return assertNeverCadence(schedule.cadence);
63748
+ }
63749
+ }
63750
+ function nextFutureWeekly(schedule, now, startAt) {
63751
+ const time3 = parseLocalTime(schedule.localTime);
63752
+ if (!time3)
63753
+ return null;
63754
+ if (!Number.isInteger(schedule.dayOfWeek) || schedule.dayOfWeek === void 0)
63755
+ return null;
63756
+ const candidate = new Date(now.getTime());
63757
+ candidate.setHours(time3.hour, time3.minute, 0, 0);
63758
+ const daysForward = (schedule.dayOfWeek - candidate.getDay() + 7) % 7;
63759
+ candidate.setDate(candidate.getDate() + daysForward);
63760
+ if (candidate.getTime() <= now.getTime()) {
63761
+ candidate.setDate(candidate.getDate() + 7);
63762
+ }
63763
+ while (candidate.getTime() < startAt.getTime()) {
63764
+ candidate.setDate(candidate.getDate() + 7);
63765
+ }
63766
+ return { dueAt: candidate, key: candidate.toISOString().slice(0, 10) };
63767
+ }
63768
+ function nextFutureMonthly(schedule, now, startAt) {
63769
+ const time3 = parseLocalTime(schedule.localTime);
63770
+ if (!time3)
63771
+ return null;
63772
+ if (!Number.isInteger(schedule.dayOfMonth) || schedule.dayOfMonth === void 0)
63773
+ return null;
63774
+ let candidate = clampedMonthlyDate(now.getFullYear(), now.getMonth(), schedule.dayOfMonth, time3.hour, time3.minute);
63775
+ if (candidate.getTime() <= now.getTime()) {
63776
+ candidate = clampedMonthlyDate(candidate.getFullYear(), candidate.getMonth() + 1, schedule.dayOfMonth, time3.hour, time3.minute);
63777
+ }
63778
+ while (candidate.getTime() < startAt.getTime()) {
63779
+ candidate = clampedMonthlyDate(candidate.getFullYear(), candidate.getMonth() + 1, schedule.dayOfMonth, time3.hour, time3.minute);
63780
+ }
63781
+ return { dueAt: candidate, key: monthlyKey(candidate) };
63782
+ }
63783
+ function nextFutureInterval(schedule, now, interval, intervalMs) {
63784
+ if (!Number.isInteger(interval) || interval === void 0 || interval < 1)
63785
+ return null;
63786
+ const anchor = recurringStartAt(schedule);
63787
+ if (!anchor)
63788
+ return null;
63789
+ const time3 = schedule.cadence === "interval_days" ? parseLocalTime(schedule.localTime) : null;
63790
+ const dueAt = new Date(anchor.getTime());
63791
+ if (time3)
63792
+ dueAt.setHours(time3.hour, time3.minute, 0, 0);
63793
+ const totalIntervalMs = interval * intervalMs;
63794
+ if (dueAt.getTime() > now.getTime()) {
63795
+ return { dueAt, key: intervalKey(dueAt, schedule.cadence) };
63796
+ }
63797
+ const elapsedMs = now.getTime() - dueAt.getTime();
63798
+ const intervalsToAdvance = Math.floor(elapsedMs / totalIntervalMs) + 1;
63799
+ dueAt.setTime(dueAt.getTime() + intervalsToAdvance * totalIntervalMs);
63800
+ return { dueAt, key: intervalKey(dueAt, schedule.cadence) };
63801
+ }
63802
+ function latestDueWeekly(schedule, now, startAt) {
63803
+ const time3 = parseLocalTime(schedule.localTime);
63804
+ if (!time3)
63805
+ return null;
63806
+ if (!Number.isInteger(schedule.dayOfWeek) || schedule.dayOfWeek === void 0)
63807
+ return null;
63808
+ const candidate = new Date(now.getTime());
63809
+ candidate.setHours(time3.hour, time3.minute, 0, 0);
63810
+ const daysBack = (candidate.getDay() - schedule.dayOfWeek + 7) % 7;
63811
+ candidate.setDate(candidate.getDate() - daysBack);
63812
+ if (candidate.getTime() < startAt.getTime()) {
63813
+ while (candidate.getTime() < startAt.getTime()) {
63814
+ candidate.setDate(candidate.getDate() + 7);
63815
+ }
63816
+ } else if (candidate.getTime() > now.getTime()) {
63817
+ candidate.setDate(candidate.getDate() - 7);
63818
+ }
63819
+ if (candidate.getTime() < startAt.getTime())
63820
+ return null;
63821
+ return { dueAt: candidate, key: candidate.toISOString().slice(0, 10) };
63822
+ }
63823
+ function latestDueMonthly(schedule, now, startAt) {
63824
+ const time3 = parseLocalTime(schedule.localTime);
63825
+ if (!time3)
63826
+ return null;
63827
+ if (!Number.isInteger(schedule.dayOfMonth) || schedule.dayOfMonth === void 0)
63828
+ return null;
63829
+ let candidate = clampedMonthlyDate(now.getFullYear(), now.getMonth(), schedule.dayOfMonth, time3.hour, time3.minute);
63830
+ if (candidate.getTime() > now.getTime()) {
63831
+ candidate = clampedMonthlyDate(candidate.getFullYear(), candidate.getMonth() - 1, schedule.dayOfMonth, time3.hour, time3.minute);
63832
+ }
63833
+ while (candidate.getTime() < startAt.getTime()) {
63834
+ candidate = clampedMonthlyDate(candidate.getFullYear(), candidate.getMonth() + 1, schedule.dayOfMonth, time3.hour, time3.minute);
63835
+ }
63836
+ return { dueAt: candidate, key: monthlyKey(candidate) };
63837
+ }
63838
+ function latestDueInterval(schedule, now, interval, intervalMs) {
63839
+ if (!Number.isInteger(interval) || interval === void 0 || interval < 1)
63840
+ return null;
63841
+ const anchor = recurringStartAt(schedule);
63842
+ if (!anchor)
63843
+ return null;
63844
+ const time3 = schedule.cadence === "interval_days" ? parseLocalTime(schedule.localTime) : null;
63845
+ const dueAt = new Date(anchor.getTime());
63846
+ if (time3)
63847
+ dueAt.setHours(time3.hour, time3.minute, 0, 0);
63848
+ const totalIntervalMs = interval * intervalMs;
63849
+ if (dueAt.getTime() > now.getTime()) {
63850
+ return { dueAt, key: intervalKey(dueAt, schedule.cadence) };
63851
+ }
63852
+ const elapsedMs = now.getTime() - dueAt.getTime();
63853
+ const intervalsElapsed = Math.floor(elapsedMs / totalIntervalMs);
63854
+ dueAt.setTime(dueAt.getTime() + intervalsElapsed * totalIntervalMs);
63855
+ return { dueAt, key: intervalKey(dueAt, schedule.cadence) };
63856
+ }
63857
+ function assertNeverCadence(cadence) {
63858
+ throw new Error(`Unhandled recurring cadence: ${String(cadence)}`);
63859
+ }
63860
+ var PREVIEW_CAP = 1e4;
63861
+ function lifetimeSpendEstimate(schedule, amount, now) {
63862
+ const isBounded = schedule.maxOccurrences !== void 0 || schedule.expiresAt !== void 0;
63863
+ const perWeek = formatRate(amount, runsPerWeek(schedule));
63864
+ const perMonth = formatRate(amount, runsPerMonth(schedule));
63865
+ if (!isBounded) {
63866
+ return { bounded: false, perWeek, perMonth };
63867
+ }
63868
+ const remaining = previewUpcoming(schedule, now, PREVIEW_CAP).length;
63869
+ const totalAmount = multiplyDecimalString(amount, remaining);
63870
+ return { bounded: true, totalRuns: remaining, totalAmount, perWeek, perMonth };
63871
+ }
63872
+ function runsPerWeek(schedule) {
63873
+ switch (schedule.cadence) {
63874
+ case "weekly":
63875
+ return 1;
63876
+ case "monthly":
63877
+ return 7 / 30.4375;
63878
+ case "interval_days":
63879
+ return schedule.intervalDays && schedule.intervalDays > 0 ? 7 / schedule.intervalDays : 0;
63880
+ case "interval_hours":
63881
+ return schedule.intervalHours && schedule.intervalHours > 0 ? 168 / schedule.intervalHours : 0;
63882
+ case "interval_minutes":
63883
+ return schedule.intervalMinutes && schedule.intervalMinutes > 0 ? 10080 / schedule.intervalMinutes : 0;
63884
+ default:
63885
+ return 0;
63886
+ }
63887
+ }
63888
+ function runsPerMonth(schedule) {
63889
+ switch (schedule.cadence) {
63890
+ case "weekly":
63891
+ return 30.4375 / 7;
63892
+ case "monthly":
63893
+ return 1;
63894
+ case "interval_days":
63895
+ return schedule.intervalDays && schedule.intervalDays > 0 ? 30.4375 / schedule.intervalDays : 0;
63896
+ case "interval_hours":
63897
+ return schedule.intervalHours && schedule.intervalHours > 0 ? 730.5 / schedule.intervalHours : 0;
63898
+ case "interval_minutes":
63899
+ return schedule.intervalMinutes && schedule.intervalMinutes > 0 ? 43830 / schedule.intervalMinutes : 0;
63900
+ default:
63901
+ return 0;
63902
+ }
63903
+ }
63904
+ function formatRate(amount, multiplier) {
63905
+ const value = Number(amount) * multiplier;
63906
+ if (!Number.isFinite(value))
63907
+ return "0";
63908
+ return value.toFixed(6).replace(/\.?0+$/, "");
63909
+ }
63910
+ function multiplyDecimalString(value, factor) {
63911
+ if (!Number.isInteger(factor) || factor < 0)
63912
+ return "0";
63913
+ if (factor === 0)
63914
+ return "0";
63915
+ const trimmed = value.trim();
63916
+ const match = /^(\d+)(?:\.(\d+))?$/.exec(trimmed);
63917
+ if (!match)
63918
+ return "0";
63919
+ const whole = match[1];
63920
+ const fraction = match[2] ?? "";
63921
+ const decimals = fraction.length;
63922
+ if (decimals === 0)
63923
+ return (BigInt(whole) * BigInt(factor)).toString();
63924
+ const raw = BigInt(whole + fraction) * BigInt(factor);
63925
+ const rawStr = raw.toString().padStart(decimals + 1, "0");
63926
+ const head = rawStr.slice(0, -decimals);
63927
+ const tail = rawStr.slice(-decimals).replace(/0+$/, "");
63928
+ return tail ? `${head}.${tail}` : head;
63929
+ }
63930
+
63931
+ // ../workflow/dist/index.js
63932
+ var WorkflowValidationError = class extends Error {
63933
+ code;
63934
+ path;
63935
+ constructor(code2, message, path) {
63936
+ super(message);
63937
+ this.code = code2;
63938
+ this.name = "WorkflowValidationError";
63939
+ this.path = path;
63940
+ }
63941
+ };
63942
+ function evaluatePlanGuardrails(input) {
63943
+ const plan = isPlainRecord(input.plan) ? input.plan : {};
63944
+ const parameters = normalizeStringRecord(input.parameters ?? valueRecord(plan.parameters));
63945
+ const fields = normalizePlanFields(input.fields ?? plan.fields);
63946
+ const source = stringValue(input.source) ?? stringValue(plan.source) ?? "template";
63947
+ const category = stringValue(input.category) ?? stringValue(plan.category) ?? "custom";
63948
+ const actionType = stringValue(input.actionType) ?? stringValue(plan.actionType) ?? "manual_review";
63949
+ const templateId = stringValue(input.templateId) ?? stringValue(plan.templateId) ?? "";
63950
+ const templateTitle = stringValue(input.templateTitle) ?? stringValue(plan.templateTitle) ?? "";
63951
+ const cluster = stringValue(input.cluster) ?? stringValue(plan.cluster) ?? "devnet";
63952
+ const userNotes = stringValue(input.userNotes) ?? stringValue(plan.userNotes) ?? "";
63953
+ const prompt2 = stringValue(input.prompt) ?? stringValue(plan.prompt) ?? "";
63954
+ const violations = [];
63955
+ collectForbiddenGuardrailViolations({
63956
+ value: {
63957
+ ...plan,
63958
+ ...input.prompt !== void 0 ? { prompt: prompt2 } : {},
63959
+ ...input.userNotes !== void 0 ? { userNotes } : {}
63960
+ },
63961
+ path: "$.plan",
63962
+ violations
63963
+ });
63964
+ collectUnsafeAiClaimViolations({
63965
+ value: {
63966
+ intent: plan.intent,
63967
+ route: plan.route,
63968
+ risk: plan.risk,
63969
+ approval: plan.approval,
63970
+ safeguards: plan.safeguards,
63971
+ prompt: prompt2,
63972
+ userNotes,
63973
+ parameters,
63974
+ fields
63975
+ },
63976
+ path: "$.plan",
63977
+ source,
63978
+ violations
63979
+ });
63980
+ if (isQueueableWorkflowAction(actionType)) {
63981
+ collectMissingConstraintViolations(actionType, parameters, violations);
63982
+ }
63983
+ if (source === "ai") {
63984
+ collectAiWarningViolations(plan, actionType, parameters, violations);
63985
+ }
63986
+ const finalizationRequirement = finalizationRequirementForAction(actionType);
63987
+ const constraintSnapshot = planConstraintSnapshot({
63988
+ source,
63989
+ category,
63990
+ actionType,
63991
+ templateId,
63992
+ templateTitle,
63993
+ cluster,
63994
+ parameters,
63995
+ fields,
63996
+ userNotes
63997
+ });
63998
+ const constraintFingerprint = stableWorkflowFingerprint(constraintSnapshot);
63999
+ const constraintHash = stableWorkflowHash(constraintSnapshot);
64000
+ const verdict = violations.some((violation) => violation.severity === "block") ? "block" : violations.some((violation) => violation.severity === "warn") ? "warn" : "pass";
64001
+ return {
64002
+ verdict,
64003
+ source,
64004
+ actionType,
64005
+ finalizationRequirement,
64006
+ constraintFingerprint,
64007
+ constraintHash,
64008
+ violations,
64009
+ summary: guardrailSummary(verdict, finalizationRequirement, violations)
64010
+ };
64011
+ }
64012
+ function assertPlanGuardrails(input) {
64013
+ const report = evaluatePlanGuardrails(input);
64014
+ if (report.verdict === "block") {
64015
+ const first = report.violations.find((violation) => violation.severity === "block");
64016
+ throw new WorkflowValidationError("ai_guardrail_blocked", first?.message ?? "Plan is blocked by Agentic AI guardrails.", first?.path);
64017
+ }
64018
+ return report;
64019
+ }
64020
+ function planConstraintSnapshot(input) {
64021
+ return {
64022
+ source: input.source ?? "template",
64023
+ category: input.category ?? "custom",
64024
+ actionType: input.actionType ?? "manual_review",
64025
+ templateId: input.templateId ?? "",
64026
+ templateTitle: input.templateTitle ?? "",
64027
+ cluster: input.cluster ?? "devnet",
64028
+ parameters: normalizeStringRecord(input.parameters),
64029
+ fields: normalizePlanFields(input.fields),
64030
+ ...input.userNotes ? { userNotes: input.userNotes } : {}
64031
+ };
64032
+ }
64033
+ function stableWorkflowFingerprint(value) {
64034
+ const serialized = stableJson(value);
64035
+ let hash = 2166136261;
64036
+ for (let index = 0; index < serialized.length; index += 1) {
64037
+ hash ^= serialized.charCodeAt(index);
64038
+ hash = Math.imul(hash, 16777619);
64039
+ }
64040
+ return `wf_${(hash >>> 0).toString(16).padStart(8, "0")}`;
64041
+ }
64042
+ function stableWorkflowHash(value) {
64043
+ return sha256Hex(stableJson(value));
64044
+ }
64045
+ function isQueueableWorkflowAction(actionType) {
64046
+ return actionType === "transfer_sol" || actionType === "transfer_spl" || actionType === "swap" || actionType === "recurring_payment";
64047
+ }
64048
+ function finalizationRequirementForAction(actionType) {
64049
+ if (actionType === "transfer_sol" || actionType === "transfer_spl" || actionType === "swap" || actionType === "custom_transaction") {
64050
+ return "transaction_preview";
64051
+ }
64052
+ if (actionType === "recurring_payment") {
64053
+ return "wallet_decision_proof";
64054
+ }
64055
+ if (actionType === "manual_review") {
64056
+ return "wallet_decision_proof";
64057
+ }
64058
+ return "none";
64059
+ }
64060
+ var FORBIDDEN_EXACT_KEYS = /* @__PURE__ */ new Set([
64061
+ "seedphrase",
64062
+ "recoveryphrase",
64063
+ "mnemonic",
64064
+ "privatekey",
64065
+ "secretkey",
64066
+ "delegatedsigner",
64067
+ "delegatesigner",
64068
+ "unlimitedapproval"
64069
+ ]);
64070
+ function collectForbiddenGuardrailViolations(input) {
64071
+ if (!input.value || typeof input.value !== "object") {
64072
+ if (typeof input.value === "string") {
64073
+ collectForbiddenTextViolations(input.value, input.path, input.violations);
64074
+ }
64075
+ return;
64076
+ }
64077
+ if (Array.isArray(input.value)) {
64078
+ input.value.forEach((entry, index) => collectForbiddenGuardrailViolations({
64079
+ value: entry,
64080
+ path: `${input.path}[${index}]`,
64081
+ violations: input.violations
64082
+ }));
64083
+ return;
64084
+ }
64085
+ for (const [key, entry] of Object.entries(input.value)) {
64086
+ const normalized = key.replace(/[^a-z0-9]/gi, "").toLowerCase();
64087
+ const path = `${input.path}.${key}`;
64088
+ if (FORBIDDEN_EXACT_KEYS.has(normalized) || normalized.includes("privatekey") || normalized.includes("secretkey")) {
64089
+ input.violations.push({
64090
+ code: "forbidden_secret",
64091
+ severity: "block",
64092
+ message: `${path} is not accepted by Agentic workflow guardrails.`,
64093
+ path
64094
+ });
64095
+ }
64096
+ if ((normalized.includes("approvalauthority") || normalized.includes("signingauthority") || normalized.includes("authority")) && indicatesUnlimitedAuthority(entry)) {
64097
+ input.violations.push({
64098
+ code: "forbidden_authority",
64099
+ severity: "block",
64100
+ message: `${path} cannot grant unlimited approval authority.`,
64101
+ path
64102
+ });
64103
+ }
64104
+ collectForbiddenGuardrailViolations({ value: entry, path, violations: input.violations });
64105
+ }
64106
+ }
64107
+ function collectForbiddenTextViolations(text, path, violations) {
64108
+ const normalized = normalizeGuardrailText(text);
64109
+ const secretRequest = /\b(share|send|enter|paste|provide|export|store|upload|reveal|recover)\b.{0,60}\b(seed phrase|recovery phrase|mnemonic|private key|secret key)\b/.test(normalized) || /\b(seed phrase|recovery phrase|mnemonic|private key|secret key)\b.{0,60}\b(ai|agent|server|cloud|provider)\b/.test(normalized);
64110
+ if (secretRequest) {
64111
+ violations.push({
64112
+ code: "forbidden_secret_request",
64113
+ severity: "block",
64114
+ message: "Plans cannot request seed phrases, private keys, recovery phrases, or secret keys.",
64115
+ path
64116
+ });
64117
+ }
64118
+ const authorityRequest = /\b(grant|give|create|use|authorize|allow|enable)\b.{0,60}\b(delegated signer|delegate signer|server signer|unlimited approval|unrestricted authority|unlimited authority)\b/.test(normalized) || /\b(unlimited approval|unrestricted authority|server signer|delegated signer)\b/.test(normalized);
64119
+ if (authorityRequest && !/\b(no|never|without|cannot|must not|do not|reject|block|forbid|forbidden|disallow)\b.{0,60}\b(unlimited approval|unrestricted authority|server signer|delegated signer)\b/.test(normalized)) {
64120
+ violations.push({
64121
+ code: "forbidden_authority_request",
64122
+ severity: "block",
64123
+ message: "Plans cannot create delegated signers, server signers, or unlimited approval authority.",
64124
+ path
64125
+ });
64126
+ }
64127
+ }
64128
+ function collectUnsafeAiClaimViolations(input) {
64129
+ if (typeof input.value === "string") {
64130
+ if (input.source === "ai") {
64131
+ collectUnsafeAiTextClaims(input.value, input.path, input.violations);
64132
+ }
64133
+ return;
64134
+ }
64135
+ if (!input.value || typeof input.value !== "object")
64136
+ return;
64137
+ if (Array.isArray(input.value)) {
64138
+ input.value.forEach((entry, index) => collectUnsafeAiClaimViolations({
64139
+ value: entry,
64140
+ path: `${input.path}[${index}]`,
64141
+ source: input.source,
64142
+ violations: input.violations
64143
+ }));
64144
+ return;
64145
+ }
64146
+ for (const [key, entry] of Object.entries(input.value)) {
64147
+ collectUnsafeAiClaimViolations({
64148
+ value: entry,
64149
+ path: `${input.path}.${key}`,
64150
+ source: input.source,
64151
+ violations: input.violations
64152
+ });
64153
+ }
64154
+ }
64155
+ function collectUnsafeAiTextClaims(text, path, violations) {
64156
+ const normalized = normalizeGuardrailText(text);
64157
+ const claims = [
64158
+ {
64159
+ code: "ai_claims_approved",
64160
+ pattern: /\b(already|pre|auto)[-\s]?(approved|approval)\b|\bapproved automatically\b/,
64161
+ message: "AI drafts cannot claim that wallet approval has already happened."
64162
+ },
64163
+ {
64164
+ code: "ai_claims_signed",
64165
+ pattern: /\b(already|pre|auto)[-\s]?(signed|signing)\b|\bsigned automatically\b/,
64166
+ message: "AI drafts cannot claim that a wallet signature has already happened."
64167
+ },
64168
+ {
64169
+ code: "ai_claims_submitted",
64170
+ pattern: /\b(already|pre|auto)[-\s]?(submitted|executed|broadcast|sent)\b|\bsubmitted automatically\b/,
64171
+ message: "AI drafts cannot claim that a transaction has already been submitted or executed."
64172
+ },
64173
+ {
64174
+ code: "ai_bypasses_wallet",
64175
+ pattern: /\b(no|without|skip|bypass)\b.{0,40}\b(wallet|approval|signature|signing)\b|\bdoes not require\b.{0,40}\b(wallet|approval|signature|signing)\b/,
64176
+ message: "AI drafts cannot bypass wallet approval or signing."
64177
+ },
64178
+ {
64179
+ code: "ai_claims_safe",
64180
+ pattern: /\b(guaranteed safe|risk[-\s]?free|100%\s+safe|safe to sign|guaranteed profit|guaranteed return|cannot fail|fully reversible)\b/,
64181
+ message: "AI drafts cannot claim that a transaction is guaranteed safe, profitable, reversible, or risk-free."
64182
+ }
64183
+ ];
64184
+ for (const claim of claims) {
64185
+ if (claim.pattern.test(normalized)) {
64186
+ violations.push({
64187
+ code: claim.code,
64188
+ severity: "block",
64189
+ message: claim.message,
64190
+ path
64191
+ });
64192
+ }
64193
+ }
64194
+ }
64195
+ function collectMissingConstraintViolations(actionType, parameters, violations) {
64196
+ const required2 = requiredConstraintGroups(actionType);
64197
+ for (const group of required2) {
64198
+ if (!group.keys.some((key) => hasStringParam(parameters, key))) {
64199
+ violations.push({
64200
+ code: "missing_executable_constraint",
64201
+ severity: "block",
64202
+ message: `${group.label} is required before this plan can enter Approval Inbox.`,
64203
+ path: `$.parameters.${group.keys[0]}`
64204
+ });
64205
+ }
64206
+ }
64207
+ const amount = firstPresentParam(parameters, ["amount", "amountSol", "inputAmount", "plannedAmount"]);
64208
+ if (amount !== void 0 && !(Number(amount) > 0)) {
64209
+ violations.push({
64210
+ code: "invalid_amount_constraint",
64211
+ severity: "block",
64212
+ message: "Amount must be a positive number before this plan can enter Approval Inbox.",
64213
+ path: "$.parameters.amount"
64214
+ });
64215
+ }
64216
+ }
64217
+ function collectAiWarningViolations(plan, actionType, parameters, violations) {
64218
+ for (const key of ["route", "risk", "approval"]) {
64219
+ const value = stringValue(plan[key]);
64220
+ if (!value || value.length < 12) {
64221
+ violations.push({
64222
+ code: "vague_ai_review_text",
64223
+ severity: "warn",
64224
+ message: `AI ${key} text should be explicit before review.`,
64225
+ path: `$.plan.${key}`
64226
+ });
64227
+ }
64228
+ }
64229
+ if (isQueueableWorkflowAction(actionType) && !firstPresentParam(parameters, ["memo", "note", "reason"])) {
64230
+ violations.push({
64231
+ code: "missing_context_note",
64232
+ severity: "warn",
64233
+ message: "A memo or reason is recommended for queueable AI plans.",
64234
+ path: "$.parameters.memo"
64235
+ });
64236
+ }
64237
+ }
64238
+ function requiredConstraintGroups(actionType) {
64239
+ if (actionType === "transfer_sol") {
64240
+ return [
64241
+ { label: "Recipient", keys: ["recipient", "recipientAddress"] },
64242
+ { label: "Amount", keys: ["amount", "amountSol"] }
64243
+ ];
64244
+ }
64245
+ if (actionType === "transfer_spl") {
64246
+ return [
64247
+ { label: "Token", keys: ["token"] },
64248
+ { label: "Recipient", keys: ["recipient", "recipientAddress"] },
64249
+ { label: "Amount", keys: ["amount"] }
64250
+ ];
64251
+ }
64252
+ if (actionType === "swap") {
64253
+ return [
64254
+ { label: "Input token", keys: ["inputToken"] },
64255
+ { label: "Output token", keys: ["outputToken"] },
64256
+ { label: "Amount", keys: ["amount", "inputAmount"] },
64257
+ { label: "Slippage cap", keys: ["slippageBps"] }
64258
+ ];
64259
+ }
64260
+ if (actionType === "recurring_payment") {
64261
+ return [
64262
+ { label: "Token", keys: ["token"] },
64263
+ { label: "Recipient", keys: ["recipient", "recipientAddress"] },
64264
+ { label: "Amount", keys: ["amount"] },
64265
+ { label: "Cadence", keys: ["cadence"] }
64266
+ ];
64267
+ }
64268
+ return [];
64269
+ }
64270
+ function guardrailSummary(verdict, finalizationRequirement, violations) {
64271
+ if (verdict === "block") {
64272
+ return violations.find((violation) => violation.severity === "block")?.message ?? "Plan is blocked by guardrails.";
64273
+ }
64274
+ if (verdict === "warn") {
64275
+ return violations.find((violation) => violation.severity === "warn")?.message ?? "Plan has guardrail warnings.";
64276
+ }
64277
+ if (finalizationRequirement === "transaction_preview") {
64278
+ return "Plan passed guardrails and requires transaction preview before wallet approval.";
64279
+ }
64280
+ if (finalizationRequirement === "wallet_decision_proof") {
64281
+ return "Plan passed guardrails and requires explicit wallet decision proof.";
64282
+ }
64283
+ return "Plan passed guardrails.";
64284
+ }
64285
+ function normalizeGuardrailText(value) {
64286
+ return value.toLowerCase().replace(/\s+/g, " ").trim();
64287
+ }
64288
+ function hasStringParam(parameters, key) {
64289
+ return Boolean(parameters[key]?.trim());
64290
+ }
64291
+ function firstPresentParam(parameters, keys) {
64292
+ for (const key of keys) {
64293
+ const value = parameters[key]?.trim();
64294
+ if (value)
64295
+ return value;
64296
+ }
64297
+ return void 0;
64298
+ }
64299
+ function normalizeStringRecord(value) {
64300
+ if (!isPlainRecord(value))
64301
+ return {};
64302
+ const output = {};
64303
+ for (const [key, entry] of Object.entries(value)) {
64304
+ if (typeof entry === "string")
64305
+ output[key] = entry;
64306
+ }
64307
+ return output;
64308
+ }
64309
+ function normalizePlanFields(value) {
64310
+ if (!Array.isArray(value))
64311
+ return [];
64312
+ return value.filter((entry) => {
64313
+ return Boolean(isPlainRecord(entry) && typeof entry.label === "string" && typeof entry.value === "string");
64314
+ }).map((entry) => ({ label: entry.label, value: entry.value }));
64315
+ }
64316
+ function valueRecord(value) {
64317
+ return isPlainRecord(value) ? value : void 0;
64318
+ }
64319
+ function stringValue(value) {
64320
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
64321
+ }
64322
+ function isPlainRecord(input) {
64323
+ return isPlainObject2(input);
64324
+ }
64325
+ function stableJson(value) {
64326
+ return JSON.stringify(sortJson(value));
64327
+ }
64328
+ var SHA256_K = [
64329
+ 1116352408,
64330
+ 1899447441,
64331
+ 3049323471,
64332
+ 3921009573,
64333
+ 961987163,
64334
+ 1508970993,
64335
+ 2453635748,
64336
+ 2870763221,
64337
+ 3624381080,
64338
+ 310598401,
64339
+ 607225278,
64340
+ 1426881987,
64341
+ 1925078388,
64342
+ 2162078206,
64343
+ 2614888103,
64344
+ 3248222580,
64345
+ 3835390401,
64346
+ 4022224774,
64347
+ 264347078,
64348
+ 604807628,
64349
+ 770255983,
64350
+ 1249150122,
64351
+ 1555081692,
64352
+ 1996064986,
64353
+ 2554220882,
64354
+ 2821834349,
64355
+ 2952996808,
64356
+ 3210313671,
64357
+ 3336571891,
64358
+ 3584528711,
64359
+ 113926993,
64360
+ 338241895,
64361
+ 666307205,
64362
+ 773529912,
64363
+ 1294757372,
64364
+ 1396182291,
64365
+ 1695183700,
64366
+ 1986661051,
64367
+ 2177026350,
64368
+ 2456956037,
64369
+ 2730485921,
64370
+ 2820302411,
64371
+ 3259730800,
64372
+ 3345764771,
64373
+ 3516065817,
64374
+ 3600352804,
64375
+ 4094571909,
64376
+ 275423344,
64377
+ 430227734,
64378
+ 506948616,
64379
+ 659060556,
64380
+ 883997877,
64381
+ 958139571,
64382
+ 1322822218,
64383
+ 1537002063,
64384
+ 1747873779,
64385
+ 1955562222,
64386
+ 2024104815,
64387
+ 2227730452,
64388
+ 2361852424,
64389
+ 2428436474,
64390
+ 2756734187,
64391
+ 3204031479,
64392
+ 3329325298
64393
+ ];
64394
+ function sha256Hex(value) {
64395
+ const bytes = utf8Bytes(value);
64396
+ const bitLength = bytes.length * 8;
64397
+ bytes.push(128);
64398
+ while (bytes.length % 64 !== 56)
64399
+ bytes.push(0);
64400
+ const high = Math.floor(bitLength / 4294967296);
64401
+ const low = bitLength >>> 0;
64402
+ for (const word of [high, low]) {
64403
+ bytes.push(word >>> 24 & 255, word >>> 16 & 255, word >>> 8 & 255, word & 255);
64404
+ }
64405
+ let h0 = 1779033703;
64406
+ let h1 = 3144134277;
64407
+ let h2 = 1013904242;
64408
+ let h3 = 2773480762;
64409
+ let h4 = 1359893119;
64410
+ let h5 = 2600822924;
64411
+ let h6 = 528734635;
64412
+ let h7 = 1541459225;
64413
+ const w3 = new Array(64);
64414
+ for (let offset = 0; offset < bytes.length; offset += 64) {
64415
+ for (let i = 0; i < 16; i += 1) {
64416
+ const index = offset + i * 4;
64417
+ w3[i] = (bytes[index] ?? 0) << 24 | (bytes[index + 1] ?? 0) << 16 | (bytes[index + 2] ?? 0) << 8 | (bytes[index + 3] ?? 0);
64418
+ }
64419
+ for (let i = 16; i < 64; i += 1) {
64420
+ const s0 = rotr(w3[i - 15], 7) ^ rotr(w3[i - 15], 18) ^ w3[i - 15] >>> 3;
64421
+ const s1 = rotr(w3[i - 2], 17) ^ rotr(w3[i - 2], 19) ^ w3[i - 2] >>> 10;
64422
+ w3[i] = w3[i - 16] + s0 + w3[i - 7] + s1 >>> 0;
64423
+ }
64424
+ let a = h0;
64425
+ let b3 = h1;
64426
+ let c = h2;
64427
+ let d = h3;
64428
+ let e = h4;
64429
+ let f = h5;
64430
+ let g2 = h6;
64431
+ let h = h7;
64432
+ for (let i = 0; i < 64; i += 1) {
64433
+ const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
64434
+ const ch = e & f ^ ~e & g2;
64435
+ const temp1 = h + s1 + ch + SHA256_K[i] + w3[i] >>> 0;
64436
+ const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
64437
+ const maj = a & b3 ^ a & c ^ b3 & c;
64438
+ const temp2 = s0 + maj >>> 0;
64439
+ h = g2;
64440
+ g2 = f;
64441
+ f = e;
64442
+ e = d + temp1 >>> 0;
64443
+ d = c;
64444
+ c = b3;
64445
+ b3 = a;
64446
+ a = temp1 + temp2 >>> 0;
64447
+ }
64448
+ h0 = h0 + a >>> 0;
64449
+ h1 = h1 + b3 >>> 0;
64450
+ h2 = h2 + c >>> 0;
64451
+ h3 = h3 + d >>> 0;
64452
+ h4 = h4 + e >>> 0;
64453
+ h5 = h5 + f >>> 0;
64454
+ h6 = h6 + g2 >>> 0;
64455
+ h7 = h7 + h >>> 0;
64456
+ }
64457
+ return [h0, h1, h2, h3, h4, h5, h6, h7].map((word) => word.toString(16).padStart(8, "0")).join("");
64458
+ }
64459
+ function rotr(value, bits) {
64460
+ return value >>> bits | value << 32 - bits;
64461
+ }
64462
+ function utf8Bytes(value) {
64463
+ const bytes = [];
64464
+ for (let index = 0; index < value.length; index += 1) {
64465
+ let codePoint = value.charCodeAt(index);
64466
+ if (codePoint >= 55296 && codePoint <= 56319) {
64467
+ const next = value.charCodeAt(index + 1);
64468
+ if (next >= 56320 && next <= 57343) {
64469
+ codePoint = 65536 + (codePoint - 55296 << 10) + (next - 56320);
64470
+ index += 1;
64471
+ } else {
64472
+ codePoint = 65533;
64473
+ }
64474
+ } else if (codePoint >= 56320 && codePoint <= 57343) {
64475
+ codePoint = 65533;
64476
+ }
64477
+ if (codePoint < 128) {
64478
+ bytes.push(codePoint);
64479
+ } else if (codePoint < 2048) {
64480
+ bytes.push(192 | codePoint >> 6, 128 | codePoint & 63);
64481
+ } else if (codePoint < 65536) {
64482
+ bytes.push(224 | codePoint >> 12, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
64483
+ } else {
64484
+ bytes.push(240 | codePoint >> 18, 128 | codePoint >> 12 & 63, 128 | codePoint >> 6 & 63, 128 | codePoint & 63);
64485
+ }
64486
+ }
64487
+ return bytes;
64488
+ }
64489
+ function sortJson(value) {
64490
+ if (Array.isArray(value)) {
64491
+ return value.map(sortJson);
64492
+ }
64493
+ if (value && typeof value === "object") {
64494
+ const output = {};
64495
+ for (const key of Object.keys(value).sort()) {
64496
+ const entry = value[key];
64497
+ if (entry !== void 0)
64498
+ output[key] = sortJson(entry);
64499
+ }
64500
+ return output;
64501
+ }
64502
+ return value;
64503
+ }
64504
+ function indicatesUnlimitedAuthority(value) {
64505
+ if (value === true)
64506
+ return true;
64507
+ if (typeof value === "string") {
64508
+ const normalized = value.toLowerCase();
64509
+ return normalized.includes("unlimited") || normalized.includes("delegate") || normalized.includes("any amount");
64510
+ }
64511
+ if (typeof value === "number")
64512
+ return !Number.isFinite(value);
64513
+ return false;
64514
+ }
64515
+ function isPlainObject2(input) {
64516
+ if (typeof input !== "object" || input === null || Array.isArray(input))
64517
+ return false;
64518
+ const prototype = Object.getPrototypeOf(input);
64519
+ return prototype === Object.prototype || prototype === null;
64520
+ }
64521
+
63627
64522
  // ../mcp-server/dist/amounts.js
63628
64523
  function parseDecimalAmount(value, decimals, label) {
63629
64524
  const trimmed = value.trim();
@@ -63709,7 +64604,8 @@ function normalizeConfig(input) {
63709
64604
  ...DEFAULT_CONFIG.jupiter,
63710
64605
  ...input.jupiter ?? {}
63711
64606
  };
63712
- return { cluster, rpcUrl, mainnet, tokens, jupiter };
64607
+ const recurring = input.recurring;
64608
+ return { cluster, rpcUrl, mainnet, tokens, jupiter, ...recurring !== void 0 && { recurring } };
63713
64609
  }
63714
64610
  function requireMainnetEnabled(config2) {
63715
64611
  if (config2.cluster === "mainnet-beta" && !config2.mainnet.enabled) {
@@ -64193,6 +65089,21 @@ function buildRecurringPaymentInput(input, walletAddress, config2) {
64193
65089
  const rawAmount = parseDecimalAmount(amount, tokenConfig.decimals, `${tokenConfig.symbol} recurring payment amount`);
64194
65090
  assertMaxAmount(rawAmount, tokenConfig.maxTransfer, tokenConfig.decimals, `${tokenConfig.symbol} recurring payment amount`);
64195
65091
  }
65092
+ const expiresAt = normalizeExpiresAt(input.expiresAt);
65093
+ const notifications = normalizeNotifications(input.notifications);
65094
+ enforceRecurringPolicy(config2.recurring, token, amount, {
65095
+ cadence: schedule.cadence,
65096
+ dayOfWeek: schedule.dayOfWeek,
65097
+ dayOfMonth: schedule.dayOfMonth,
65098
+ intervalDays: schedule.intervalDays,
65099
+ intervalHours: schedule.intervalHours,
65100
+ intervalMinutes: schedule.intervalMinutes,
65101
+ localTime: schedule.localTime,
65102
+ startAt: schedule.startAt,
65103
+ maxOccurrences: schedule.maxOccurrences,
65104
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
65105
+ expiresAt
65106
+ });
64196
65107
  return {
64197
65108
  walletAddress,
64198
65109
  cluster: config2.cluster,
@@ -64200,9 +65111,83 @@ function buildRecurringPaymentInput(input, walletAddress, config2) {
64200
65111
  recipient,
64201
65112
  amount,
64202
65113
  ...schedule,
64203
- ...note !== void 0 && { note }
65114
+ ...note !== void 0 && { note },
65115
+ ...expiresAt !== void 0 && { expiresAt },
65116
+ ...notifications !== void 0 && { notifications }
64204
65117
  };
64205
65118
  }
65119
+ function enforceRecurringPolicy(policy, token, amount, cadenceFields) {
65120
+ if (!policy)
65121
+ return;
65122
+ const lifetime = policy.maxLifetimeAmount?.[token];
65123
+ const perWeek = policy.maxPerWeekAmount?.[token];
65124
+ const perMonth = policy.maxPerMonthAmount?.[token];
65125
+ if (!lifetime && !perWeek && !perMonth)
65126
+ return;
65127
+ const estimate = lifetimeSpendEstimate(cadenceFields, amount, /* @__PURE__ */ new Date());
65128
+ if (lifetime && estimate.bounded && estimate.totalAmount && compareDecimal(estimate.totalAmount, lifetime) > 0) {
65129
+ throw new ProtocolError("invalid_request", `This schedule would spend up to ${estimate.totalAmount} ${token} total, exceeding your configured lifetime cap of ${lifetime} ${token}.`);
65130
+ }
65131
+ if (perWeek && compareDecimal(estimate.perWeek, perWeek) > 0) {
65132
+ throw new ProtocolError("invalid_request", `This schedule would spend up to ${estimate.perWeek} ${token} per week, exceeding your configured cap of ${perWeek} ${token} per week.`);
65133
+ }
65134
+ if (perMonth && compareDecimal(estimate.perMonth, perMonth) > 0) {
65135
+ throw new ProtocolError("invalid_request", `This schedule would spend up to ${estimate.perMonth} ${token} per month, exceeding your configured cap of ${perMonth} ${token} per month.`);
65136
+ }
65137
+ }
65138
+ function compareDecimal(left, right) {
65139
+ const a = Number(left);
65140
+ const b3 = Number(right);
65141
+ if (!Number.isFinite(a) || !Number.isFinite(b3))
65142
+ return 0;
65143
+ if (a < b3)
65144
+ return -1;
65145
+ if (a > b3)
65146
+ return 1;
65147
+ return 0;
65148
+ }
65149
+ function normalizeNotifications(value) {
65150
+ if (value === void 0 || value === null)
65151
+ return void 0;
65152
+ if (typeof value !== "object" || Array.isArray(value)) {
65153
+ throw new ProtocolError("invalid_request", "notifications must be an object.");
65154
+ }
65155
+ const obj = value;
65156
+ const result = {};
65157
+ if (obj.inApp !== void 0) {
65158
+ if (typeof obj.inApp !== "boolean") {
65159
+ throw new ProtocolError("invalid_request", "notifications.inApp must be a boolean.");
65160
+ }
65161
+ result.inApp = obj.inApp;
65162
+ }
65163
+ if (obj.webhookUrl !== void 0 && obj.webhookUrl !== null && obj.webhookUrl !== "") {
65164
+ if (typeof obj.webhookUrl !== "string") {
65165
+ throw new ProtocolError("invalid_request", "notifications.webhookUrl must be a string.");
65166
+ }
65167
+ try {
65168
+ const parsed = new URL(obj.webhookUrl);
65169
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:")
65170
+ throw new Error("protocol");
65171
+ } catch {
65172
+ throw new ProtocolError("invalid_request", "notifications.webhookUrl must be a valid http(s) URL.");
65173
+ }
65174
+ result.webhookUrl = obj.webhookUrl;
65175
+ }
65176
+ return Object.keys(result).length > 0 ? result : void 0;
65177
+ }
65178
+ function normalizeExpiresAt(value) {
65179
+ if (value === void 0 || value === null || value === "")
65180
+ return void 0;
65181
+ if (typeof value !== "string") {
65182
+ throw new ProtocolError("invalid_request", "expiresAt must be an ISO timestamp string.");
65183
+ }
65184
+ const trimmed = value.trim();
65185
+ const parsed = new Date(trimmed);
65186
+ if (Number.isNaN(parsed.getTime())) {
65187
+ throw new ProtocolError("invalid_request", "expiresAt must be a valid ISO timestamp.");
65188
+ }
65189
+ return trimmed;
65190
+ }
64206
65191
  function normalizeRecurringSchedule(input) {
64207
65192
  if (input.maxOccurrences !== void 0 && (!Number.isInteger(input.maxOccurrences) || input.maxOccurrences < 1)) {
64208
65193
  throw new ProtocolError("invalid_request", "maxOccurrences must be a positive integer when provided.");
@@ -64542,10 +65527,13 @@ var JsonPreparedActionStore = class {
64542
65527
  }
64543
65528
  async listRecurringPaymentViews(now = /* @__PURE__ */ new Date()) {
64544
65529
  const state = await this.read();
64545
- return state.recurringPayments.map((payment) => ({
64546
- ...payment,
64547
- ...nextRecurringOccurrence(payment, now) ? { nextDueAt: nextRecurringOccurrence(payment, now).dueAt.toISOString() } : {}
64548
- })).sort((left, right) => {
65530
+ return state.recurringPayments.map((payment) => {
65531
+ const nextDueAt = nextRecurringDueAt(payment, now);
65532
+ return {
65533
+ ...payment,
65534
+ ...nextDueAt ? { nextDueAt } : {}
65535
+ };
65536
+ }).sort((left, right) => {
64549
65537
  const leftDue = left.nextDueAt ?? "9999-12-31T23:59:59.999Z";
64550
65538
  const rightDue = right.nextDueAt ?? "9999-12-31T23:59:59.999Z";
64551
65539
  return leftDue.localeCompare(rightDue);
@@ -64587,7 +65575,13 @@ var JsonPreparedActionStore = class {
64587
65575
  if (payment.maxOccurrences !== void 0 && (payment.occurrencesCreated ?? 0) >= payment.maxOccurrences) {
64588
65576
  continue;
64589
65577
  }
64590
- const occurrence = latestRecurringOccurrence(payment, now);
65578
+ if (payment.expiresAt) {
65579
+ const expiry = new Date(payment.expiresAt);
65580
+ if (!Number.isNaN(expiry.getTime()) && now.getTime() >= expiry.getTime()) {
65581
+ continue;
65582
+ }
65583
+ }
65584
+ const occurrence = latestDueOccurrence(payment, now);
64591
65585
  if (!occurrence || occurrence.dueAt.getTime() > now.getTime())
64592
65586
  continue;
64593
65587
  const exists = state.actions.some((action2) => action2.recurringId === payment.id && action2.occurrenceKey === occurrence.key);
@@ -64679,105 +65673,13 @@ function normalizePreparedAction(action) {
64679
65673
  }
64680
65674
  };
64681
65675
  }
64682
- function latestRecurringOccurrence(payment, now) {
64683
- const startAt = recurringStartAt(payment);
64684
- if (!startAt) {
64685
- return null;
64686
- }
64687
- let occurrence;
64688
- switch (payment.cadence) {
64689
- case "weekly":
64690
- occurrence = latestWeeklyOccurrence(payment, now);
64691
- break;
64692
- case "monthly":
64693
- occurrence = latestMonthlyOccurrence(payment, now);
64694
- break;
64695
- case "interval_days":
64696
- occurrence = latestIntervalOccurrence(payment, now, payment.intervalDays, 24 * 60 * 60 * 1e3);
64697
- break;
64698
- case "interval_hours":
64699
- occurrence = latestIntervalOccurrence(payment, now, payment.intervalHours, 60 * 60 * 1e3);
64700
- break;
64701
- case "interval_minutes":
64702
- occurrence = latestIntervalOccurrence(payment, now, payment.intervalMinutes, 60 * 1e3);
64703
- break;
64704
- }
64705
- if (!occurrence || occurrence.dueAt.getTime() < startAt.getTime()) {
64706
- return null;
64707
- }
64708
- return occurrence;
64709
- }
64710
- function nextRecurringOccurrence(payment, now) {
64711
- const startAt = recurringStartAt(payment);
64712
- if (!startAt)
64713
- return null;
65676
+ function nextRecurringDueAt(payment, now = /* @__PURE__ */ new Date()) {
64714
65677
  if (payment.status !== "active")
64715
65678
  return null;
64716
65679
  if (payment.maxOccurrences !== void 0 && (payment.occurrencesCreated ?? 0) >= payment.maxOccurrences) {
64717
65680
  return null;
64718
65681
  }
64719
- switch (payment.cadence) {
64720
- case "weekly":
64721
- return nextWeeklyOccurrence(payment, now, startAt);
64722
- case "monthly":
64723
- return nextMonthlyOccurrence(payment, now, startAt);
64724
- case "interval_days":
64725
- return nextIntervalOccurrence(payment, now, payment.intervalDays, 24 * 60 * 60 * 1e3);
64726
- case "interval_hours":
64727
- return nextIntervalOccurrence(payment, now, payment.intervalHours, 60 * 60 * 1e3);
64728
- case "interval_minutes":
64729
- return nextIntervalOccurrence(payment, now, payment.intervalMinutes, 60 * 1e3);
64730
- }
64731
- }
64732
- function nextWeeklyOccurrence(payment, now, startAt) {
64733
- if (!payment.localTime || !Number.isInteger(payment.dayOfWeek) || payment.dayOfWeek === void 0)
64734
- return null;
64735
- const time3 = parseLocalTime(payment.localTime);
64736
- if (!time3)
64737
- return null;
64738
- const dueAt = new Date(now);
64739
- dueAt.setHours(time3.hour, time3.minute, 0, 0);
64740
- const daysForward = (payment.dayOfWeek - dueAt.getDay() + 7) % 7;
64741
- dueAt.setDate(dueAt.getDate() + daysForward);
64742
- if (dueAt.getTime() <= now.getTime()) {
64743
- dueAt.setDate(dueAt.getDate() + 7);
64744
- }
64745
- while (dueAt.getTime() < startAt.getTime()) {
64746
- dueAt.setDate(dueAt.getDate() + 7);
64747
- }
64748
- return { dueAt, key: dueAt.toISOString().slice(0, 10) };
64749
- }
64750
- function nextMonthlyOccurrence(payment, now, startAt) {
64751
- if (!payment.localTime || !Number.isInteger(payment.dayOfMonth) || payment.dayOfMonth === void 0)
64752
- return null;
64753
- const time3 = parseLocalTime(payment.localTime);
64754
- if (!time3)
64755
- return null;
64756
- let dueAt = clampedMonthlyDate(now.getFullYear(), now.getMonth(), payment.dayOfMonth, time3.hour, time3.minute);
64757
- if (dueAt.getTime() <= now.getTime()) {
64758
- dueAt = clampedMonthlyDate(now.getFullYear(), now.getMonth() + 1, payment.dayOfMonth, time3.hour, time3.minute);
64759
- }
64760
- while (dueAt.getTime() < startAt.getTime()) {
64761
- dueAt = clampedMonthlyDate(dueAt.getFullYear(), dueAt.getMonth() + 1, payment.dayOfMonth, time3.hour, time3.minute);
64762
- }
64763
- return { dueAt, key: dueAt.toISOString().slice(0, 10) };
64764
- }
64765
- function nextIntervalOccurrence(payment, now, interval, intervalMs) {
64766
- if (!Number.isInteger(interval) || interval === void 0 || interval < 1)
64767
- return null;
64768
- const anchor = recurringStartAt(payment);
64769
- if (!anchor)
64770
- return null;
64771
- const totalIntervalMs = interval * intervalMs;
64772
- const dueAt = new Date(anchor);
64773
- if (dueAt.getTime() <= now.getTime()) {
64774
- const elapsedMs = now.getTime() - dueAt.getTime();
64775
- dueAt.setTime(dueAt.getTime() + (Math.floor(elapsedMs / totalIntervalMs) + 1) * totalIntervalMs);
64776
- }
64777
- return {
64778
- dueAt,
64779
- key: payment.cadence === "interval_days" ? dueAt.toISOString().slice(0, 10) : dueAt.toISOString()
64780
- };
65682
+ return nextFutureOccurrence(payment, now)?.dueAt.toISOString() ?? null;
64781
65683
  }
64782
65684
  function actionReceipt(action) {
64783
65685
  const recipient = typeof action.params.recipient === "string" ? action.params.recipient : void 0;
@@ -64798,93 +65700,15 @@ function actionReceipt(action) {
64798
65700
  cluster: action.cluster,
64799
65701
  createdAt: action.createdAt,
64800
65702
  completedAt: action.confirmedAt ?? action.updatedAt,
64801
- ...action.error !== void 0 && { error: action.error }
65703
+ ...action.error !== void 0 && { error: action.error },
65704
+ ...action.recurringId !== void 0 && { recurringId: action.recurringId },
65705
+ ...action.occurrenceKey !== void 0 && { occurrenceKey: action.occurrenceKey }
64802
65706
  };
64803
65707
  }
64804
65708
  function explorerUrl2(txid, cluster) {
64805
65709
  const clusterParam = cluster === "mainnet-beta" ? "" : `?cluster=${cluster}`;
64806
65710
  return `https://solscan.io/tx/${txid}${clusterParam}`;
64807
65711
  }
64808
- function latestWeeklyOccurrence(payment, now) {
64809
- if (!payment.localTime) {
64810
- return null;
64811
- }
64812
- const [hourRaw, minuteRaw] = payment.localTime.split(":");
64813
- const hour = Number(hourRaw);
64814
- const minute = Number(minuteRaw);
64815
- if (!Number.isInteger(hour) || !Number.isInteger(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
64816
- return null;
64817
- }
64818
- if (!Number.isInteger(payment.dayOfWeek) || payment.dayOfWeek === void 0) {
64819
- return null;
64820
- }
64821
- const dueAt = new Date(now);
64822
- dueAt.setHours(hour, minute, 0, 0);
64823
- const daysBack = (dueAt.getDay() - payment.dayOfWeek + 7) % 7;
64824
- dueAt.setDate(dueAt.getDate() - daysBack);
64825
- if (dueAt.getTime() > now.getTime()) {
64826
- dueAt.setDate(dueAt.getDate() - 7);
64827
- }
64828
- return { dueAt, key: dueAt.toISOString().slice(0, 10) };
64829
- }
64830
- function latestMonthlyOccurrence(payment, now) {
64831
- if (!payment.localTime) {
64832
- return null;
64833
- }
64834
- const time3 = parseLocalTime(payment.localTime);
64835
- if (!time3 || !Number.isInteger(payment.dayOfMonth) || payment.dayOfMonth === void 0) {
64836
- return null;
64837
- }
64838
- const dueAt = clampedMonthlyDate(now.getFullYear(), now.getMonth(), payment.dayOfMonth, time3.hour, time3.minute);
64839
- if (dueAt.getTime() > now.getTime()) {
64840
- dueAt.setMonth(dueAt.getMonth() - 1);
64841
- const previous = clampedMonthlyDate(dueAt.getFullYear(), dueAt.getMonth(), payment.dayOfMonth, time3.hour, time3.minute);
64842
- return { dueAt: previous, key: previous.toISOString().slice(0, 10) };
64843
- }
64844
- return { dueAt, key: dueAt.toISOString().slice(0, 10) };
64845
- }
64846
- function latestIntervalOccurrence(payment, now, interval, intervalMs) {
64847
- if (!Number.isInteger(interval) || interval === void 0 || interval < 1) {
64848
- return null;
64849
- }
64850
- const anchor = new Date(payment.startAt ?? payment.createdAt);
64851
- if (Number.isNaN(anchor.getTime())) {
64852
- return null;
64853
- }
64854
- const dueAt = new Date(anchor);
64855
- const time3 = payment.localTime ? parseLocalTime(payment.localTime) : null;
64856
- if (time3 && payment.cadence === "interval_days") {
64857
- dueAt.setHours(time3.hour, time3.minute, 0, 0);
64858
- }
64859
- if (dueAt.getTime() > now.getTime()) {
64860
- return null;
64861
- }
64862
- const elapsedMs = now.getTime() - dueAt.getTime();
64863
- const totalIntervalMs = interval * intervalMs;
64864
- const intervalsElapsed = Math.floor(elapsedMs / totalIntervalMs);
64865
- dueAt.setTime(dueAt.getTime() + intervalsElapsed * totalIntervalMs);
64866
- return {
64867
- dueAt,
64868
- key: payment.cadence === "interval_days" ? dueAt.toISOString().slice(0, 10) : dueAt.toISOString()
64869
- };
64870
- }
64871
- function recurringStartAt(payment) {
64872
- const startAt = new Date(payment.startAt ?? payment.createdAt);
64873
- return Number.isNaN(startAt.getTime()) ? null : startAt;
64874
- }
64875
- function parseLocalTime(localTime) {
64876
- const [hourRaw, minuteRaw] = localTime.split(":");
64877
- const hour = Number(hourRaw);
64878
- const minute = Number(minuteRaw);
64879
- if (!Number.isInteger(hour) || !Number.isInteger(minute) || hour < 0 || hour > 23 || minute < 0 || minute > 59) {
64880
- return null;
64881
- }
64882
- return { hour, minute };
64883
- }
64884
- function clampedMonthlyDate(year, month, dayOfMonth, hour, minute) {
64885
- const lastDay = new Date(year, month + 1, 0).getDate();
64886
- return new Date(year, month, Math.min(dayOfMonth, lastDay), hour, minute, 0, 0);
64887
- }
64888
65712
  function statusForDueAt(dueAt, now) {
64889
65713
  return new Date(dueAt).getTime() > now.getTime() ? "scheduled" : "ready";
64890
65714
  }
@@ -67204,7 +68028,7 @@ function clean(...arrays) {
67204
68028
  function createView(arr) {
67205
68029
  return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
67206
68030
  }
67207
- function rotr(word, shift) {
68031
+ function rotr2(word, shift) {
67208
68032
  return word << 32 - shift | word >>> shift;
67209
68033
  }
67210
68034
  var isLE = /* @__PURE__ */ (() => new Uint8Array(new Uint32Array([287454020]).buffer)[0] === 68)();
@@ -67758,7 +68582,7 @@ var SHA512_IV = /* @__PURE__ */ Uint32Array.from([
67758
68582
  ]);
67759
68583
 
67760
68584
  // ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha2.js
67761
- var SHA256_K = /* @__PURE__ */ Uint32Array.from([
68585
+ var SHA256_K2 = /* @__PURE__ */ Uint32Array.from([
67762
68586
  1116352408,
67763
68587
  1899447441,
67764
68588
  3049323471,
@@ -67858,15 +68682,15 @@ var SHA256 = class extends HashMD {
67858
68682
  for (let i = 16; i < 64; i++) {
67859
68683
  const W15 = SHA256_W[i - 15];
67860
68684
  const W22 = SHA256_W[i - 2];
67861
- const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
67862
- const s1 = rotr(W22, 17) ^ rotr(W22, 19) ^ W22 >>> 10;
68685
+ const s0 = rotr2(W15, 7) ^ rotr2(W15, 18) ^ W15 >>> 3;
68686
+ const s1 = rotr2(W22, 17) ^ rotr2(W22, 19) ^ W22 >>> 10;
67863
68687
  SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
67864
68688
  }
67865
68689
  let { A: A4, B: B3, C: C2, D: D3, E: E3, F: F3, G: G3, H: H5 } = this;
67866
68690
  for (let i = 0; i < 64; i++) {
67867
- const sigma1 = rotr(E3, 6) ^ rotr(E3, 11) ^ rotr(E3, 25);
67868
- const T1 = H5 + sigma1 + Chi(E3, F3, G3) + SHA256_K[i] + SHA256_W[i] | 0;
67869
- const sigma0 = rotr(A4, 2) ^ rotr(A4, 13) ^ rotr(A4, 22);
68691
+ const sigma1 = rotr2(E3, 6) ^ rotr2(E3, 11) ^ rotr2(E3, 25);
68692
+ const T1 = H5 + sigma1 + Chi(E3, F3, G3) + SHA256_K2[i] + SHA256_W[i] | 0;
68693
+ const sigma0 = rotr2(A4, 2) ^ rotr2(A4, 13) ^ rotr2(A4, 22);
67870
68694
  const T22 = sigma0 + Maj(A4, B3, C2) | 0;
67871
68695
  H5 = G3;
67872
68696
  G3 = F3;
@@ -68551,8 +69375,8 @@ function fromNumber(value, options = {}) {
68551
69375
  value: `${value}${suffix}`
68552
69376
  });
68553
69377
  }
68554
- const stringValue = (signed && value_ < 0 ? (1n << BigInt(size3 * 8)) + BigInt(value_) : value_).toString(16);
68555
- const hex = `0x${stringValue}`;
69378
+ const stringValue2 = (signed && value_ < 0 ? (1n << BigInt(size3 * 8)) + BigInt(value_) : value_).toString(16);
69379
+ const hex = `0x${stringValue2}`;
68556
69380
  if (size3)
68557
69381
  return padLeft(hex, size3);
68558
69382
  return hex;
@@ -76503,7 +77327,7 @@ var float32ArrayTag = "[object Float32Array]";
76503
77327
  var float64ArrayTag = "[object Float64Array]";
76504
77328
 
76505
77329
  // ../../node_modules/.pnpm/es-toolkit@1.44.0/node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
76506
- function isPlainObject2(value) {
77330
+ function isPlainObject3(value) {
76507
77331
  if (!value || typeof value !== "object") {
76508
77332
  return false;
76509
77333
  }
@@ -76660,7 +77484,7 @@ function areObjectsEqual(a, b3, stack, areValuesEqual) {
76660
77484
  return a.name === b3.name && a.message === b3.message;
76661
77485
  }
76662
77486
  case objectTag: {
76663
- const areEqualInstances = areObjectsEqual(a.constructor, b3.constructor, stack, areValuesEqual) || isPlainObject2(a) && isPlainObject2(b3);
77487
+ const areEqualInstances = areObjectsEqual(a.constructor, b3.constructor, stack, areValuesEqual) || isPlainObject3(a) && isPlainObject3(b3);
76664
77488
  if (!areEqualInstances) {
76665
77489
  return false;
76666
77490
  }
@@ -80941,6 +81765,7 @@ var BridgeAiPlanner = class {
80941
81765
  throw new ProtocolError("unsupported_method", "Bridge AI is not configured. Set AGENTIC_AI_API_KEY or provide a bridge session key.");
80942
81766
  }
80943
81767
  const normalizedRequest = normalizeRequest(request);
81768
+ assertAiDraftRequestAllowed(normalizedRequest);
80944
81769
  if (config2.apiFormat === "anthropic") {
80945
81770
  return this.generateAnthropicPlan(config2, normalizedRequest);
80946
81771
  }
@@ -81108,7 +81933,7 @@ function normalizeStrictAiPlan(payload, request, providerLabel) {
81108
81933
  }
81109
81934
  function aiPlanFromParsed(parsed, request) {
81110
81935
  const parameters = request.parameters;
81111
- return {
81936
+ const plan = {
81112
81937
  intent: stringOr(parsed.intent, `${request.template.title}: ${request.prompt}`),
81113
81938
  route: stringOr(parsed.route, `Draft ${request.template.actionType} request and show route details before wallet approval.`),
81114
81939
  risk: stringOr(parsed.risk, `Risk level ${request.template.risk}. Verify all visible fields before signing.`),
@@ -81122,6 +81947,67 @@ function aiPlanFromParsed(parsed, request) {
81122
81947
  fields: Object.entries(parameters).filter(([, value]) => value.trim().length > 0).map(([key, value]) => ({ label: titleCase(key), value })),
81123
81948
  safeguards: normalizeSafeguards(parsed.safeguards)
81124
81949
  };
81950
+ return withGuardrailReport(plan, request);
81951
+ }
81952
+ function assertAiDraftRequestAllowed(request) {
81953
+ try {
81954
+ assertPlanGuardrails({
81955
+ source: "ai",
81956
+ category: request.template.category,
81957
+ actionType: request.template.actionType,
81958
+ templateId: request.template.id,
81959
+ templateTitle: request.template.title,
81960
+ parameters: request.parameters,
81961
+ userNotes: request.userNotes,
81962
+ prompt: request.prompt,
81963
+ plan: {
81964
+ source: "ai",
81965
+ category: request.template.category,
81966
+ actionType: request.template.actionType,
81967
+ templateId: request.template.id,
81968
+ templateTitle: request.template.title,
81969
+ parameters: request.parameters,
81970
+ prompt: request.prompt,
81971
+ userNotes: request.userNotes,
81972
+ intent: request.prompt,
81973
+ route: "AI draft only. Wallet approval is required later.",
81974
+ risk: `Requested risk level ${request.template.risk}.`,
81975
+ approval: "Wallet approval is required before signing or submitting."
81976
+ }
81977
+ });
81978
+ } catch (err) {
81979
+ if (err instanceof Error) {
81980
+ throw new ProtocolError("invalid_request", err.message);
81981
+ }
81982
+ throw err;
81983
+ }
81984
+ }
81985
+ function withGuardrailReport(plan, request) {
81986
+ try {
81987
+ const report = assertPlanGuardrails({
81988
+ plan: { ...plan },
81989
+ source: plan.source,
81990
+ category: plan.category,
81991
+ actionType: plan.actionType,
81992
+ templateId: request.template.id,
81993
+ templateTitle: plan.templateTitle,
81994
+ parameters: plan.parameters,
81995
+ fields: plan.fields,
81996
+ userNotes: plan.userNotes,
81997
+ prompt: request.prompt
81998
+ });
81999
+ return {
82000
+ ...plan,
82001
+ guardrailReport: report,
82002
+ constraintFingerprint: report.constraintFingerprint,
82003
+ ...report.constraintHash ? { constraintHash: report.constraintHash } : {}
82004
+ };
82005
+ } catch (err) {
82006
+ if (err instanceof Error) {
82007
+ throw new ProtocolError("invalid_request", err.message);
82008
+ }
82009
+ throw err;
82010
+ }
81125
82011
  }
81126
82012
  function isPlanJson(value) {
81127
82013
  return typeof value.intent === "string" && typeof value.route === "string" && typeof value.risk === "string" && typeof value.approval === "string" && Array.isArray(value.safeguards) && value.safeguards.every((entry) => typeof entry === "string");
@@ -81465,6 +82351,14 @@ async function handleRequest(req, res, backend, actionConfig, preparedActions, l
81465
82351
  writeJson(res, 200, { artifact: await requireLabArtifactStore(labArtifacts).upsertArtifact(artifact) });
81466
82352
  return;
81467
82353
  }
82354
+ if (req.method === "POST" && url.pathname === "/bridge/lab-artifacts/delete") {
82355
+ const body = await readJson(req);
82356
+ if (!body.artifactId) {
82357
+ throw new ProtocolError("invalid_request", "Missing artifactId.");
82358
+ }
82359
+ writeJson(res, 200, { deleted: await requireLabArtifactStore(labArtifacts).deleteArtifact(body.artifactId) });
82360
+ return;
82361
+ }
81468
82362
  if (req.method === "GET" && url.pathname === "/bridge/health") {
81469
82363
  const caps = await backend.capabilities().catch(() => null);
81470
82364
  const rpcWritable = actionConfig ? await checkRpcWritable(actionConfig.rpcUrl) : { ok: false, message: "Action config unavailable." };
@@ -81880,6 +82774,13 @@ var JsonLabArtifactStore = class {
81880
82774
  const state = await this.read();
81881
82775
  return sortArtifacts(state.artifacts);
81882
82776
  }
82777
+ async deleteArtifact(id) {
82778
+ return this.mutate((state) => {
82779
+ const before = state.artifacts.length;
82780
+ state.artifacts = state.artifacts.filter((artifact) => artifact.id !== id);
82781
+ return state.artifacts.length !== before;
82782
+ });
82783
+ }
81883
82784
  getStoragePath() {
81884
82785
  return this.path;
81885
82786
  }
@@ -82574,7 +83475,7 @@ async function approvePreparedAction(state, idOrIndex) {
82574
83475
  body: JSON.stringify({ actionId: action.id })
82575
83476
  });
82576
83477
  printOk(state.options, `Approved prepared action ${action.id}.`);
82577
- console.log(stableJson(result));
83478
+ console.log(stableJson2(result));
82578
83479
  await printInbox(state, "all").catch(() => void 0);
82579
83480
  }
82580
83481
  async function rejectPreparedAction(state, idOrIndex, reason) {
@@ -82585,7 +83486,7 @@ async function rejectPreparedAction(state, idOrIndex, reason) {
82585
83486
  body: JSON.stringify({ actionId: action.id, reason: reason ?? "Rejected from terminal." })
82586
83487
  });
82587
83488
  printOk(state.options, `Rejected prepared action ${action.id}.`);
82588
- console.log(stableJson(result));
83489
+ console.log(stableJson2(result));
82589
83490
  }
82590
83491
  async function archivePreparedAction(state, idOrIndex) {
82591
83492
  const action = await resolveAction(state, idOrIndex);
@@ -82594,7 +83495,7 @@ async function archivePreparedAction(state, idOrIndex) {
82594
83495
  body: JSON.stringify({ actionId: action.id })
82595
83496
  });
82596
83497
  printOk(state.options, `Archived prepared action ${action.id}.`);
82597
- console.log(stableJson(result));
83498
+ console.log(stableJson2(result));
82598
83499
  }
82599
83500
  async function inspectPreparedActionInteractive(state, idOrIndex) {
82600
83501
  const action = await resolveAction(state, idOrIndex);
@@ -82623,7 +83524,7 @@ async function runScheduleCommand(state, rl, args) {
82623
83524
  body: JSON.stringify({ recurringId })
82624
83525
  });
82625
83526
  printOk(state.options, `Recurring payment ${op}: ${recurringId}`);
82626
- console.log(stableJson(result2));
83527
+ console.log(stableJson2(result2));
82627
83528
  return;
82628
83529
  }
82629
83530
  await requireWalletConnected(state);
@@ -82660,7 +83561,7 @@ async function runScheduleCommand(state, rl, args) {
82660
83561
  body: JSON.stringify(body)
82661
83562
  });
82662
83563
  printOk(state.options, "Recurring approval created.");
82663
- console.log(stableJson(result));
83564
+ console.log(stableJson2(result));
82664
83565
  }
82665
83566
  async function runPlanCommand(state, rl, naturalLanguage) {
82666
83567
  printSection("Agent Plan");
@@ -82730,7 +83631,7 @@ async function runResearchCommand(state, rl, args) {
82730
83631
  const inlineInput = args.slice(1).join(" ");
82731
83632
  const input = inlineInput || await prompt(rl, "Artifact input", lab.defaultInput);
82732
83633
  const artifact = await buildResearchArtifact(state.options, lab, input);
82733
- console.log(stableJson(artifact));
83634
+ console.log(stableJson2(artifact));
82734
83635
  if (await confirm(rl, "Sign this research artifact?", true)) {
82735
83636
  const approval = await signTextWithWallet(
82736
83637
  state,
@@ -82755,7 +83656,7 @@ async function runQuoteCommand(state, rl) {
82755
83656
  method: "POST",
82756
83657
  body: JSON.stringify({ amount, inputToken, outputToken, slippageBps })
82757
83658
  });
82758
- console.log(stableJson(result));
83659
+ console.log(stableJson2(result));
82759
83660
  }
82760
83661
  async function printReceipts(state) {
82761
83662
  const response = await bridgeRequest(state.options, "/bridge/receipts");
@@ -83068,7 +83969,7 @@ async function handleWalletHostRequest(root, req, res) {
83068
83969
  }
83069
83970
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "127.0.0.1"}`);
83070
83971
  if (url.pathname === WALLET_HOST_HEALTH_PATH) {
83071
- const body2 = req.method === "HEAD" ? Buffer.alloc(0) : `${stableJson({ ok: true, service: "agentic-wallet-host" })}
83972
+ const body2 = req.method === "HEAD" ? Buffer.alloc(0) : `${stableJson2({ ok: true, service: "agentic-wallet-host" })}
83072
83973
  `;
83073
83974
  writeStaticResponse(res, 200, "application/json; charset=utf-8", body2);
83074
83975
  return;
@@ -83148,7 +84049,7 @@ async function ensureRuntimeFiles(options) {
83148
84049
  await mkdir3(dirname3(options.preparedActionsPath), { recursive: true });
83149
84050
  await mkdir3(dirname3(options.labArtifactsPath), { recursive: true });
83150
84051
  if (!existsSync(options.configPath)) {
83151
- await writeFile3(options.configPath, `${stableJson(DEFAULT_CONFIG)}
84052
+ await writeFile3(options.configPath, `${stableJson2(DEFAULT_CONFIG)}
83152
84053
  `, "utf8");
83153
84054
  }
83154
84055
  }
@@ -83427,7 +84328,7 @@ async function saveResearchArtifact(options, artifact) {
83427
84328
  await mkdir3(dir, { recursive: true });
83428
84329
  const existing = await readJsonFile(path).catch(() => ({ artifacts: [] }));
83429
84330
  const artifacts = [artifact, ...(existing.artifacts ?? []).filter((item) => item.id !== artifact.id)].slice(0, 50);
83430
- await writeFile3(path, `${stableJson({ artifacts })}
84331
+ await writeFile3(path, `${stableJson2({ artifacts })}
83431
84332
  `, "utf8");
83432
84333
  }
83433
84334
  async function readJsonFile(path) {
@@ -83503,7 +84404,7 @@ function agentPlanSigningMessage(plan) {
83503
84404
  `Risk: ${plan.risk}`,
83504
84405
  `Constraints: ${plan.constraints.join(" | ")}`,
83505
84406
  `Created: ${plan.createdAt}`,
83506
- `Hash: ${sha2564(stableJson(plan))}`
84407
+ `Hash: ${sha2564(stableJson2(plan))}`
83507
84408
  ].join("\n");
83508
84409
  }
83509
84410
  function researchSigningMessage(artifact) {
@@ -83557,7 +84458,7 @@ async function buildResearchArtifact(options, lab, input) {
83557
84458
  cluster,
83558
84459
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
83559
84460
  };
83560
- const payloadHash = sha2564(stableJson(baseArtifact));
84461
+ const payloadHash = sha2564(stableJson2(baseArtifact));
83561
84462
  return { ...baseArtifact, payloadHash };
83562
84463
  }
83563
84464
  function filterPreparedActions(actions, filter) {
@@ -83614,7 +84515,7 @@ function printPreparedActionDetail(action, row) {
83614
84515
  console.log(` Error: ${action.error}`);
83615
84516
  }
83616
84517
  if (Object.keys(action.params).length > 0) {
83617
- console.log(` Params: ${stableJson(action.params).replace(/\n/g, "\n ")}`);
84518
+ console.log(` Params: ${stableJson2(action.params).replace(/\n/g, "\n ")}`);
83618
84519
  }
83619
84520
  }
83620
84521
  function renderPreparedActionsCompact(actions) {
@@ -83711,7 +84612,7 @@ function printDoctor(options, doctor) {
83711
84612
  const walletHost = isRecord(doctor.walletHost) ? doctor.walletHost : {};
83712
84613
  console.log(`Browser wallet host: ${walletHost.reachable ? "reachable" : "offline"}`);
83713
84614
  if (options.json) {
83714
- console.log(stableJson(doctor));
84615
+ console.log(stableJson2(doctor));
83715
84616
  }
83716
84617
  }
83717
84618
  function renderBanner(state) {
@@ -83788,10 +84689,10 @@ function printResult(result, options) {
83788
84689
  return;
83789
84690
  }
83790
84691
  if (options.json) {
83791
- console.log(stableJson(result));
84692
+ console.log(stableJson2(result));
83792
84693
  return;
83793
84694
  }
83794
- console.log(stableJson(result));
84695
+ console.log(stableJson2(result));
83795
84696
  }
83796
84697
  function printSection(title) {
83797
84698
  console.log(`
@@ -84095,16 +84996,16 @@ function stripTrailingSlash(value) {
84095
84996
  function isRecord(value) {
84096
84997
  return typeof value === "object" && value !== null && !Array.isArray(value);
84097
84998
  }
84098
- function stableJson(value) {
84099
- return JSON.stringify(sortJson(value), null, 2);
84999
+ function stableJson2(value) {
85000
+ return JSON.stringify(sortJson2(value), null, 2);
84100
85001
  }
84101
- function sortJson(value) {
85002
+ function sortJson2(value) {
84102
85003
  if (Array.isArray(value)) {
84103
- return value.map(sortJson);
85004
+ return value.map(sortJson2);
84104
85005
  }
84105
85006
  if (isRecord(value)) {
84106
85007
  return Object.fromEntries(
84107
- Object.keys(value).sort().map((key) => [key, sortJson(value[key])])
85008
+ Object.keys(value).sort().map((key) => [key, sortJson2(value[key])])
84108
85009
  );
84109
85010
  }
84110
85011
  return value;