@t2000/engine 0.30.0 → 0.31.1

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.d.ts CHANGED
@@ -832,19 +832,10 @@ declare const healthCheckTool: Tool<{}, {
832
832
 
833
833
  declare const ratesInfoTool: Tool<{}, _t2000_sdk.RatesResult>;
834
834
 
835
- interface TxRecord {
836
- digest: string;
837
- action: string;
838
- amount?: number;
839
- asset?: string;
840
- recipient?: string;
841
- timestamp: number;
842
- gasCost?: number;
843
- }
844
835
  declare const transactionHistoryTool: Tool<{
845
836
  limit?: number | undefined;
846
837
  }, {
847
- transactions: TxRecord[];
838
+ transactions: _t2000_sdk.TransactionRecord[];
848
839
  count: number;
849
840
  }>;
850
841
 
package/dist/index.js CHANGED
@@ -980,13 +980,15 @@ function parseRpcTx(tx, address) {
980
980
  const recipientChange = inflows.find((c) => c.coinType === coinType);
981
981
  recipient = recipientChange ? resolveOwner(recipientChange.owner) ?? void 0 : void 0;
982
982
  }
983
+ const timestampMs = Number(tx.timestampMs ?? 0);
983
984
  return {
984
985
  digest: tx.digest,
985
986
  action: classifyAction(moveCallTargets, commandTypes),
986
987
  amount,
987
988
  asset,
988
989
  recipient,
989
- timestamp: Number(tx.timestampMs ?? 0),
990
+ timestamp: timestampMs,
991
+ date: timestampMs > 0 ? new Date(timestampMs).toISOString() : void 0,
990
992
  gasCost
991
993
  };
992
994
  }
@@ -2645,6 +2647,7 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
2645
2647
  };
2646
2648
  }
2647
2649
  if (template === "health_simulator") {
2650
+ const roundedDebt = totalBorrows >= 1 ? Math.round(totalBorrows) : totalBorrows > 0 ? parseFloat(totalBorrows.toFixed(4)) : 0;
2648
2651
  return {
2649
2652
  data: {
2650
2653
  __canvas: true,
@@ -2653,7 +2656,7 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
2653
2656
  templateData: {
2654
2657
  available: true,
2655
2658
  initialCollateral: totalSavings > 0 ? Math.round(totalSavings) : 1500,
2656
- initialDebt: totalBorrows > 0 ? Math.round(totalBorrows) : 500,
2659
+ initialDebt: roundedDebt > 0 ? roundedDebt : totalSavings > 0 ? 0 : 500,
2657
2660
  currentHf: healthFactor
2658
2661
  }
2659
2662
  },
@@ -2821,6 +2824,216 @@ var activitySummaryTool = buildTool({
2821
2824
  }
2822
2825
  }
2823
2826
  });
2827
+ function getApiConfig(context) {
2828
+ const apiUrl = context.env?.ALLOWANCE_API_URL;
2829
+ const internalKey = context.env?.AUDRIC_INTERNAL_KEY;
2830
+ const address = context.walletAddress;
2831
+ return { apiUrl, internalKey, address };
2832
+ }
2833
+ function parseCronFromDescription(input) {
2834
+ const lower = input.toLowerCase().trim();
2835
+ if (/^\d+\s/.test(lower) || lower.startsWith("*")) return lower;
2836
+ if (/every\s*day|daily/.test(lower)) {
2837
+ const hourMatch = lower.match(/at\s*(\d{1,2})\s*(am|pm)?/i);
2838
+ let hour = 9;
2839
+ if (hourMatch) {
2840
+ hour = parseInt(hourMatch[1], 10);
2841
+ if (hourMatch[2]?.toLowerCase() === "pm" && hour < 12) hour += 12;
2842
+ if (hourMatch[2]?.toLowerCase() === "am" && hour === 12) hour = 0;
2843
+ }
2844
+ return `0 ${hour} * * *`;
2845
+ }
2846
+ const dayMap = {
2847
+ sunday: 0,
2848
+ monday: 1,
2849
+ tuesday: 2,
2850
+ wednesday: 3,
2851
+ thursday: 4,
2852
+ friday: 5,
2853
+ saturday: 6,
2854
+ sun: 0,
2855
+ mon: 1,
2856
+ tue: 2,
2857
+ wed: 3,
2858
+ thu: 4,
2859
+ fri: 5,
2860
+ sat: 6
2861
+ };
2862
+ for (const [name, num] of Object.entries(dayMap)) {
2863
+ if (lower.includes(name)) {
2864
+ const hourMatch = lower.match(/at\s*(\d{1,2})\s*(am|pm)?/i);
2865
+ let hour = 9;
2866
+ if (hourMatch) {
2867
+ hour = parseInt(hourMatch[1], 10);
2868
+ if (hourMatch[2]?.toLowerCase() === "pm" && hour < 12) hour += 12;
2869
+ if (hourMatch[2]?.toLowerCase() === "am" && hour === 12) hour = 0;
2870
+ }
2871
+ return `0 ${hour} * * ${num}`;
2872
+ }
2873
+ }
2874
+ if (/weekly/.test(lower)) return "0 9 * * 1";
2875
+ if (/monthly/.test(lower)) return "0 9 1 * *";
2876
+ if (/biweekly|bi-weekly|every\s*two\s*weeks/.test(lower)) return "0 9 1,15 * *";
2877
+ throw new Error(`Could not parse schedule: "${input}". Try "every friday at 9am", "daily", "weekly", or a cron expression like "0 9 * * 5".`);
2878
+ }
2879
+ var createScheduleTool = buildTool({
2880
+ name: "create_schedule",
2881
+ description: 'Create a recurring scheduled action (DCA). Supports: save, swap, repay. User says "save $50 every Friday" or "DCA $100 into savings weekly". First 5 executions require user confirmation (trust ladder), then becomes autonomous.',
2882
+ inputSchema: z.object({
2883
+ actionType: z.enum(["save", "swap", "repay"]).describe("Action type: save, swap, or repay"),
2884
+ amount: z.number().positive().describe("Amount in USD for each execution"),
2885
+ schedule: z.string().describe('Schedule description: "every friday", "daily at 9am", "weekly", or a cron expression'),
2886
+ asset: z.string().optional().describe("Source asset (default: USDC)"),
2887
+ targetAsset: z.string().optional().describe("Target asset for swaps (e.g. SUI)")
2888
+ }),
2889
+ jsonSchema: {
2890
+ type: "object",
2891
+ properties: {
2892
+ actionType: { type: "string", enum: ["save", "swap", "repay"], description: "Action type" },
2893
+ amount: { type: "number", description: "Amount in USD per execution" },
2894
+ schedule: { type: "string", description: 'Schedule: "every friday", "daily at 9am", "weekly", or cron' },
2895
+ asset: { type: "string", description: "Source asset (default: USDC)" },
2896
+ targetAsset: { type: "string", description: "Target asset for swaps" }
2897
+ },
2898
+ required: ["actionType", "amount", "schedule"]
2899
+ },
2900
+ isReadOnly: false,
2901
+ permissionLevel: "confirm",
2902
+ async call(input, context) {
2903
+ const { apiUrl, internalKey, address } = getApiConfig(context);
2904
+ if (!apiUrl || !address) {
2905
+ return { data: null, displayText: "Scheduled actions are not available." };
2906
+ }
2907
+ let cronExpr;
2908
+ try {
2909
+ cronExpr = parseCronFromDescription(input.schedule);
2910
+ } catch (err) {
2911
+ return { data: null, displayText: err instanceof Error ? err.message : "Invalid schedule format." };
2912
+ }
2913
+ try {
2914
+ const res = await fetch(`${apiUrl}/api/scheduled-actions`, {
2915
+ method: "POST",
2916
+ headers: {
2917
+ "Content-Type": "application/json",
2918
+ ...internalKey ? { "x-internal-key": internalKey } : {}
2919
+ },
2920
+ body: JSON.stringify({
2921
+ address,
2922
+ actionType: input.actionType,
2923
+ amount: input.amount,
2924
+ asset: input.asset ?? "USDC",
2925
+ targetAsset: input.targetAsset,
2926
+ cronExpr
2927
+ })
2928
+ });
2929
+ if (!res.ok) {
2930
+ const err = await res.json().catch(() => ({}));
2931
+ return { data: null, displayText: `Failed to create schedule: ${err.error ?? res.statusText}` };
2932
+ }
2933
+ const { action } = await res.json();
2934
+ const nextRun = new Date(action.nextRunAt);
2935
+ const nextRunLabel = nextRun.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
2936
+ const verb = input.actionType === "save" ? "save" : input.actionType === "swap" ? "swap" : "repay";
2937
+ return {
2938
+ data: { id: action.id, actionType: input.actionType, amount: input.amount, cronExpr, nextRun: action.nextRunAt },
2939
+ displayText: `Scheduled: ${verb} $${input.amount.toFixed(2)} ${input.asset ?? "USDC"} ${input.schedule}. Next run: ${nextRunLabel}. First 5 executions require your confirmation.`
2940
+ };
2941
+ } catch (err) {
2942
+ return { data: null, displayText: `Schedule creation failed: ${err instanceof Error ? err.message : "unknown error"}` };
2943
+ }
2944
+ }
2945
+ });
2946
+ var listSchedulesTool = buildTool({
2947
+ name: "list_schedules",
2948
+ description: "List all scheduled/recurring actions (DCA, auto-save, auto-repay) for the user.",
2949
+ inputSchema: z.object({}),
2950
+ jsonSchema: { type: "object", properties: {}, required: [] },
2951
+ isReadOnly: true,
2952
+ permissionLevel: "auto",
2953
+ async call(_input, context) {
2954
+ const { apiUrl, internalKey, address } = getApiConfig(context);
2955
+ if (!apiUrl || !address) {
2956
+ return { data: null, displayText: "Scheduled actions are not available." };
2957
+ }
2958
+ try {
2959
+ const res = await fetch(`${apiUrl}/api/scheduled-actions?address=${address}`, {
2960
+ headers: {
2961
+ ...internalKey ? { "x-internal-key": internalKey } : {}
2962
+ }
2963
+ });
2964
+ if (!res.ok) {
2965
+ return { data: null, displayText: "Failed to fetch schedules." };
2966
+ }
2967
+ const { actions } = await res.json();
2968
+ if (actions.length === 0) {
2969
+ return { data: { actions: [] }, displayText: "No scheduled actions found." };
2970
+ }
2971
+ const lines = actions.map((a) => {
2972
+ const status = !a.enabled ? "paused" : a.confirmationsCompleted >= a.confirmationsRequired ? "autonomous" : `${a.confirmationsCompleted}/${a.confirmationsRequired} confirmed`;
2973
+ const next = new Date(a.nextRunAt).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
2974
+ return `\u2022 ${a.actionType} $${a.amount.toFixed(2)} ${a.asset} \u2014 ${status} \u2014 next: ${next} \u2014 total: $${a.totalAmountUsdc.toFixed(2)} over ${a.totalExecutions} runs`;
2975
+ });
2976
+ return {
2977
+ data: { actions },
2978
+ displayText: `Found ${actions.length} scheduled action(s):
2979
+ ${lines.join("\n")}`
2980
+ };
2981
+ } catch (err) {
2982
+ return { data: null, displayText: `Failed to list schedules: ${err instanceof Error ? err.message : "unknown error"}` };
2983
+ }
2984
+ }
2985
+ });
2986
+ var cancelScheduleTool = buildTool({
2987
+ name: "cancel_schedule",
2988
+ description: "Cancel or pause a scheduled action. Provide the schedule ID or describe which one to cancel.",
2989
+ inputSchema: z.object({
2990
+ scheduleId: z.string().describe("The ID of the scheduled action to cancel/pause"),
2991
+ action: z.enum(["delete", "pause", "resume"]).optional().describe("delete (default), pause, or resume")
2992
+ }),
2993
+ jsonSchema: {
2994
+ type: "object",
2995
+ properties: {
2996
+ scheduleId: { type: "string", description: "Schedule ID" },
2997
+ action: { type: "string", enum: ["delete", "pause", "resume"], description: "delete, pause, or resume" }
2998
+ },
2999
+ required: ["scheduleId"]
3000
+ },
3001
+ isReadOnly: false,
3002
+ permissionLevel: "confirm",
3003
+ async call(input, context) {
3004
+ const { apiUrl, internalKey, address } = getApiConfig(context);
3005
+ if (!apiUrl || !address) {
3006
+ return { data: null, displayText: "Scheduled actions are not available." };
3007
+ }
3008
+ const actionType = input.action ?? "delete";
3009
+ try {
3010
+ const res = await fetch(`${apiUrl}/api/scheduled-actions/${input.scheduleId}`, {
3011
+ method: "PATCH",
3012
+ headers: {
3013
+ "Content-Type": "application/json",
3014
+ ...internalKey ? { "x-internal-key": internalKey } : {}
3015
+ },
3016
+ body: JSON.stringify({
3017
+ address,
3018
+ action: actionType,
3019
+ ...actionType === "pause" ? { enabled: false } : {},
3020
+ ...actionType === "resume" ? { enabled: true } : {}
3021
+ })
3022
+ });
3023
+ if (!res.ok) {
3024
+ const err = await res.json().catch(() => ({}));
3025
+ return { data: null, displayText: `Failed to ${actionType} schedule: ${err.error ?? res.statusText}` };
3026
+ }
3027
+ const label = actionType === "delete" ? "Cancelled" : actionType === "pause" ? "Paused" : "Resumed";
3028
+ return {
3029
+ data: { id: input.scheduleId, action: actionType },
3030
+ displayText: `${label} scheduled action ${input.scheduleId.slice(0, 8)}\u2026`
3031
+ };
3032
+ } catch (err) {
3033
+ return { data: null, displayText: `Failed: ${err instanceof Error ? err.message : "unknown error"}` };
3034
+ }
3035
+ }
3036
+ });
2824
3037
  var LLAMA_API2 = "https://api.llama.fi";
2825
3038
  var YIELDS_API2 = "https://yields.llama.fi";
2826
3039
  var COINS_API = "https://coins.llama.fi";
@@ -3137,7 +3350,8 @@ var READ_TOOLS = [
3137
3350
  createInvoiceTool,
3138
3351
  spendingAnalyticsTool,
3139
3352
  yieldSummaryTool,
3140
- activitySummaryTool
3353
+ activitySummaryTool,
3354
+ listSchedulesTool
3141
3355
  ];
3142
3356
  var WRITE_TOOLS = [
3143
3357
  saveDepositTool,
@@ -3150,7 +3364,9 @@ var WRITE_TOOLS = [
3150
3364
  swapExecuteTool,
3151
3365
  voloStakeTool,
3152
3366
  voloUnstakeTool,
3153
- saveContactTool
3367
+ saveContactTool,
3368
+ createScheduleTool,
3369
+ cancelScheduleTool
3154
3370
  ];
3155
3371
  function getDefaultTools() {
3156
3372
  return [...READ_TOOLS, ...WRITE_TOOLS];