@t2000/engine 0.30.0 → 0.31.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 +215 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2821,6 +2821,216 @@ var activitySummaryTool = buildTool({
|
|
|
2821
2821
|
}
|
|
2822
2822
|
}
|
|
2823
2823
|
});
|
|
2824
|
+
function getApiConfig(context) {
|
|
2825
|
+
const apiUrl = context.env?.ALLOWANCE_API_URL;
|
|
2826
|
+
const internalKey = context.env?.AUDRIC_INTERNAL_KEY;
|
|
2827
|
+
const address = context.walletAddress;
|
|
2828
|
+
return { apiUrl, internalKey, address };
|
|
2829
|
+
}
|
|
2830
|
+
function parseCronFromDescription(input) {
|
|
2831
|
+
const lower = input.toLowerCase().trim();
|
|
2832
|
+
if (/^\d+\s/.test(lower) || lower.startsWith("*")) return lower;
|
|
2833
|
+
if (/every\s*day|daily/.test(lower)) {
|
|
2834
|
+
const hourMatch = lower.match(/at\s*(\d{1,2})\s*(am|pm)?/i);
|
|
2835
|
+
let hour = 9;
|
|
2836
|
+
if (hourMatch) {
|
|
2837
|
+
hour = parseInt(hourMatch[1], 10);
|
|
2838
|
+
if (hourMatch[2]?.toLowerCase() === "pm" && hour < 12) hour += 12;
|
|
2839
|
+
if (hourMatch[2]?.toLowerCase() === "am" && hour === 12) hour = 0;
|
|
2840
|
+
}
|
|
2841
|
+
return `0 ${hour} * * *`;
|
|
2842
|
+
}
|
|
2843
|
+
const dayMap = {
|
|
2844
|
+
sunday: 0,
|
|
2845
|
+
monday: 1,
|
|
2846
|
+
tuesday: 2,
|
|
2847
|
+
wednesday: 3,
|
|
2848
|
+
thursday: 4,
|
|
2849
|
+
friday: 5,
|
|
2850
|
+
saturday: 6,
|
|
2851
|
+
sun: 0,
|
|
2852
|
+
mon: 1,
|
|
2853
|
+
tue: 2,
|
|
2854
|
+
wed: 3,
|
|
2855
|
+
thu: 4,
|
|
2856
|
+
fri: 5,
|
|
2857
|
+
sat: 6
|
|
2858
|
+
};
|
|
2859
|
+
for (const [name, num] of Object.entries(dayMap)) {
|
|
2860
|
+
if (lower.includes(name)) {
|
|
2861
|
+
const hourMatch = lower.match(/at\s*(\d{1,2})\s*(am|pm)?/i);
|
|
2862
|
+
let hour = 9;
|
|
2863
|
+
if (hourMatch) {
|
|
2864
|
+
hour = parseInt(hourMatch[1], 10);
|
|
2865
|
+
if (hourMatch[2]?.toLowerCase() === "pm" && hour < 12) hour += 12;
|
|
2866
|
+
if (hourMatch[2]?.toLowerCase() === "am" && hour === 12) hour = 0;
|
|
2867
|
+
}
|
|
2868
|
+
return `0 ${hour} * * ${num}`;
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
if (/weekly/.test(lower)) return "0 9 * * 1";
|
|
2872
|
+
if (/monthly/.test(lower)) return "0 9 1 * *";
|
|
2873
|
+
if (/biweekly|bi-weekly|every\s*two\s*weeks/.test(lower)) return "0 9 1,15 * *";
|
|
2874
|
+
throw new Error(`Could not parse schedule: "${input}". Try "every friday at 9am", "daily", "weekly", or a cron expression like "0 9 * * 5".`);
|
|
2875
|
+
}
|
|
2876
|
+
var createScheduleTool = buildTool({
|
|
2877
|
+
name: "create_schedule",
|
|
2878
|
+
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.',
|
|
2879
|
+
inputSchema: z.object({
|
|
2880
|
+
actionType: z.enum(["save", "swap", "repay"]).describe("Action type: save, swap, or repay"),
|
|
2881
|
+
amount: z.number().positive().describe("Amount in USD for each execution"),
|
|
2882
|
+
schedule: z.string().describe('Schedule description: "every friday", "daily at 9am", "weekly", or a cron expression'),
|
|
2883
|
+
asset: z.string().optional().describe("Source asset (default: USDC)"),
|
|
2884
|
+
targetAsset: z.string().optional().describe("Target asset for swaps (e.g. SUI)")
|
|
2885
|
+
}),
|
|
2886
|
+
jsonSchema: {
|
|
2887
|
+
type: "object",
|
|
2888
|
+
properties: {
|
|
2889
|
+
actionType: { type: "string", enum: ["save", "swap", "repay"], description: "Action type" },
|
|
2890
|
+
amount: { type: "number", description: "Amount in USD per execution" },
|
|
2891
|
+
schedule: { type: "string", description: 'Schedule: "every friday", "daily at 9am", "weekly", or cron' },
|
|
2892
|
+
asset: { type: "string", description: "Source asset (default: USDC)" },
|
|
2893
|
+
targetAsset: { type: "string", description: "Target asset for swaps" }
|
|
2894
|
+
},
|
|
2895
|
+
required: ["actionType", "amount", "schedule"]
|
|
2896
|
+
},
|
|
2897
|
+
isReadOnly: false,
|
|
2898
|
+
permissionLevel: "confirm",
|
|
2899
|
+
async call(input, context) {
|
|
2900
|
+
const { apiUrl, internalKey, address } = getApiConfig(context);
|
|
2901
|
+
if (!apiUrl || !address) {
|
|
2902
|
+
return { data: null, displayText: "Scheduled actions are not available." };
|
|
2903
|
+
}
|
|
2904
|
+
let cronExpr;
|
|
2905
|
+
try {
|
|
2906
|
+
cronExpr = parseCronFromDescription(input.schedule);
|
|
2907
|
+
} catch (err) {
|
|
2908
|
+
return { data: null, displayText: err instanceof Error ? err.message : "Invalid schedule format." };
|
|
2909
|
+
}
|
|
2910
|
+
try {
|
|
2911
|
+
const res = await fetch(`${apiUrl}/api/scheduled-actions`, {
|
|
2912
|
+
method: "POST",
|
|
2913
|
+
headers: {
|
|
2914
|
+
"Content-Type": "application/json",
|
|
2915
|
+
...internalKey ? { "x-internal-key": internalKey } : {}
|
|
2916
|
+
},
|
|
2917
|
+
body: JSON.stringify({
|
|
2918
|
+
address,
|
|
2919
|
+
actionType: input.actionType,
|
|
2920
|
+
amount: input.amount,
|
|
2921
|
+
asset: input.asset ?? "USDC",
|
|
2922
|
+
targetAsset: input.targetAsset,
|
|
2923
|
+
cronExpr
|
|
2924
|
+
})
|
|
2925
|
+
});
|
|
2926
|
+
if (!res.ok) {
|
|
2927
|
+
const err = await res.json().catch(() => ({}));
|
|
2928
|
+
return { data: null, displayText: `Failed to create schedule: ${err.error ?? res.statusText}` };
|
|
2929
|
+
}
|
|
2930
|
+
const { action } = await res.json();
|
|
2931
|
+
const nextRun = new Date(action.nextRunAt);
|
|
2932
|
+
const nextRunLabel = nextRun.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
|
|
2933
|
+
const verb = input.actionType === "save" ? "save" : input.actionType === "swap" ? "swap" : "repay";
|
|
2934
|
+
return {
|
|
2935
|
+
data: { id: action.id, actionType: input.actionType, amount: input.amount, cronExpr, nextRun: action.nextRunAt },
|
|
2936
|
+
displayText: `Scheduled: ${verb} $${input.amount.toFixed(2)} ${input.asset ?? "USDC"} ${input.schedule}. Next run: ${nextRunLabel}. First 5 executions require your confirmation.`
|
|
2937
|
+
};
|
|
2938
|
+
} catch (err) {
|
|
2939
|
+
return { data: null, displayText: `Schedule creation failed: ${err instanceof Error ? err.message : "unknown error"}` };
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
});
|
|
2943
|
+
var listSchedulesTool = buildTool({
|
|
2944
|
+
name: "list_schedules",
|
|
2945
|
+
description: "List all scheduled/recurring actions (DCA, auto-save, auto-repay) for the user.",
|
|
2946
|
+
inputSchema: z.object({}),
|
|
2947
|
+
jsonSchema: { type: "object", properties: {}, required: [] },
|
|
2948
|
+
isReadOnly: true,
|
|
2949
|
+
permissionLevel: "auto",
|
|
2950
|
+
async call(_input, context) {
|
|
2951
|
+
const { apiUrl, internalKey, address } = getApiConfig(context);
|
|
2952
|
+
if (!apiUrl || !address) {
|
|
2953
|
+
return { data: null, displayText: "Scheduled actions are not available." };
|
|
2954
|
+
}
|
|
2955
|
+
try {
|
|
2956
|
+
const res = await fetch(`${apiUrl}/api/scheduled-actions?address=${address}`, {
|
|
2957
|
+
headers: {
|
|
2958
|
+
...internalKey ? { "x-internal-key": internalKey } : {}
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
if (!res.ok) {
|
|
2962
|
+
return { data: null, displayText: "Failed to fetch schedules." };
|
|
2963
|
+
}
|
|
2964
|
+
const { actions } = await res.json();
|
|
2965
|
+
if (actions.length === 0) {
|
|
2966
|
+
return { data: { actions: [] }, displayText: "No scheduled actions found." };
|
|
2967
|
+
}
|
|
2968
|
+
const lines = actions.map((a) => {
|
|
2969
|
+
const status = !a.enabled ? "paused" : a.confirmationsCompleted >= a.confirmationsRequired ? "autonomous" : `${a.confirmationsCompleted}/${a.confirmationsRequired} confirmed`;
|
|
2970
|
+
const next = new Date(a.nextRunAt).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" });
|
|
2971
|
+
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`;
|
|
2972
|
+
});
|
|
2973
|
+
return {
|
|
2974
|
+
data: { actions },
|
|
2975
|
+
displayText: `Found ${actions.length} scheduled action(s):
|
|
2976
|
+
${lines.join("\n")}`
|
|
2977
|
+
};
|
|
2978
|
+
} catch (err) {
|
|
2979
|
+
return { data: null, displayText: `Failed to list schedules: ${err instanceof Error ? err.message : "unknown error"}` };
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
});
|
|
2983
|
+
var cancelScheduleTool = buildTool({
|
|
2984
|
+
name: "cancel_schedule",
|
|
2985
|
+
description: "Cancel or pause a scheduled action. Provide the schedule ID or describe which one to cancel.",
|
|
2986
|
+
inputSchema: z.object({
|
|
2987
|
+
scheduleId: z.string().describe("The ID of the scheduled action to cancel/pause"),
|
|
2988
|
+
action: z.enum(["delete", "pause", "resume"]).optional().describe("delete (default), pause, or resume")
|
|
2989
|
+
}),
|
|
2990
|
+
jsonSchema: {
|
|
2991
|
+
type: "object",
|
|
2992
|
+
properties: {
|
|
2993
|
+
scheduleId: { type: "string", description: "Schedule ID" },
|
|
2994
|
+
action: { type: "string", enum: ["delete", "pause", "resume"], description: "delete, pause, or resume" }
|
|
2995
|
+
},
|
|
2996
|
+
required: ["scheduleId"]
|
|
2997
|
+
},
|
|
2998
|
+
isReadOnly: false,
|
|
2999
|
+
permissionLevel: "confirm",
|
|
3000
|
+
async call(input, context) {
|
|
3001
|
+
const { apiUrl, internalKey, address } = getApiConfig(context);
|
|
3002
|
+
if (!apiUrl || !address) {
|
|
3003
|
+
return { data: null, displayText: "Scheduled actions are not available." };
|
|
3004
|
+
}
|
|
3005
|
+
const actionType = input.action ?? "delete";
|
|
3006
|
+
try {
|
|
3007
|
+
const res = await fetch(`${apiUrl}/api/scheduled-actions/${input.scheduleId}`, {
|
|
3008
|
+
method: "PATCH",
|
|
3009
|
+
headers: {
|
|
3010
|
+
"Content-Type": "application/json",
|
|
3011
|
+
...internalKey ? { "x-internal-key": internalKey } : {}
|
|
3012
|
+
},
|
|
3013
|
+
body: JSON.stringify({
|
|
3014
|
+
address,
|
|
3015
|
+
action: actionType,
|
|
3016
|
+
...actionType === "pause" ? { enabled: false } : {},
|
|
3017
|
+
...actionType === "resume" ? { enabled: true } : {}
|
|
3018
|
+
})
|
|
3019
|
+
});
|
|
3020
|
+
if (!res.ok) {
|
|
3021
|
+
const err = await res.json().catch(() => ({}));
|
|
3022
|
+
return { data: null, displayText: `Failed to ${actionType} schedule: ${err.error ?? res.statusText}` };
|
|
3023
|
+
}
|
|
3024
|
+
const label = actionType === "delete" ? "Cancelled" : actionType === "pause" ? "Paused" : "Resumed";
|
|
3025
|
+
return {
|
|
3026
|
+
data: { id: input.scheduleId, action: actionType },
|
|
3027
|
+
displayText: `${label} scheduled action ${input.scheduleId.slice(0, 8)}\u2026`
|
|
3028
|
+
};
|
|
3029
|
+
} catch (err) {
|
|
3030
|
+
return { data: null, displayText: `Failed: ${err instanceof Error ? err.message : "unknown error"}` };
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
2824
3034
|
var LLAMA_API2 = "https://api.llama.fi";
|
|
2825
3035
|
var YIELDS_API2 = "https://yields.llama.fi";
|
|
2826
3036
|
var COINS_API = "https://coins.llama.fi";
|
|
@@ -3137,7 +3347,8 @@ var READ_TOOLS = [
|
|
|
3137
3347
|
createInvoiceTool,
|
|
3138
3348
|
spendingAnalyticsTool,
|
|
3139
3349
|
yieldSummaryTool,
|
|
3140
|
-
activitySummaryTool
|
|
3350
|
+
activitySummaryTool,
|
|
3351
|
+
listSchedulesTool
|
|
3141
3352
|
];
|
|
3142
3353
|
var WRITE_TOOLS = [
|
|
3143
3354
|
saveDepositTool,
|
|
@@ -3150,7 +3361,9 @@ var WRITE_TOOLS = [
|
|
|
3150
3361
|
swapExecuteTool,
|
|
3151
3362
|
voloStakeTool,
|
|
3152
3363
|
voloUnstakeTool,
|
|
3153
|
-
saveContactTool
|
|
3364
|
+
saveContactTool,
|
|
3365
|
+
createScheduleTool,
|
|
3366
|
+
cancelScheduleTool
|
|
3154
3367
|
];
|
|
3155
3368
|
function getDefaultTools() {
|
|
3156
3369
|
return [...READ_TOOLS, ...WRITE_TOOLS];
|