@roll-agent/runtime 0.22.0 → 0.23.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/engine/agent-session.js +1 -1
- package/dist/engine/compaction-semantic-state.d.ts +8 -0
- package/dist/engine/compaction-semantic-state.js +1 -1
- package/dist/engine/system-prompt.js +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1 -1
- package/dist/scheduler/calendar.d.ts +66 -0
- package/dist/scheduler/calendar.js +1 -0
- package/dist/scheduler/database-version.d.ts +6 -0
- package/dist/scheduler/database-version.js +1 -0
- package/dist/scheduler/read-only-sqlite.d.ts +4 -0
- package/dist/scheduler/read-only-sqlite.js +1 -0
- package/dist/scheduler/schedule-store.d.ts +4 -0
- package/dist/scheduler/schedule-store.js +1 -1
- package/dist/scheduler/trigger.d.ts +160 -1
- package/dist/scheduler/trigger.js +1 -1
- package/dist/scheduler/types.d.ts +2 -0
- package/dist/tool-bridge/invalid-schedule-retry.d.ts +6 -0
- package/dist/tool-bridge/invalid-schedule-retry.js +1 -0
- package/dist/tool-bridge/schedule-create-input.d.ts +91 -0
- package/dist/tool-bridge/schedule-create-input.js +1 -0
- package/dist/tool-bridge/schedule-tool.js +1 -1
- package/package.json +2 -2
|
@@ -1,29 +1,187 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const TRIGGER_KINDS: {
|
|
3
3
|
readonly interval: "interval";
|
|
4
|
+
readonly calendar: "calendar";
|
|
4
5
|
};
|
|
5
6
|
export type TriggerKind = (typeof TRIGGER_KINDS)[keyof typeof TRIGGER_KINDS];
|
|
6
7
|
export declare const intervalTriggerSchema: z.ZodObject<{
|
|
7
8
|
kind: z.ZodLiteral<"interval">;
|
|
8
9
|
everyMs: z.ZodNumber;
|
|
10
|
+
startAtMs: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
timeZone: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
9
12
|
}, "strict", z.ZodTypeAny, {
|
|
10
13
|
kind: "interval";
|
|
11
14
|
everyMs: number;
|
|
15
|
+
timeZone?: string | undefined;
|
|
16
|
+
startAtMs?: number | undefined;
|
|
12
17
|
}, {
|
|
13
18
|
kind: "interval";
|
|
14
19
|
everyMs: number;
|
|
20
|
+
timeZone?: string | undefined;
|
|
21
|
+
startAtMs?: number | undefined;
|
|
15
22
|
}>;
|
|
16
23
|
export declare const triggerSpecSchema: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
17
24
|
kind: z.ZodLiteral<"interval">;
|
|
18
25
|
everyMs: z.ZodNumber;
|
|
26
|
+
startAtMs: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
timeZone: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
19
28
|
}, "strict", z.ZodTypeAny, {
|
|
20
29
|
kind: "interval";
|
|
21
30
|
everyMs: number;
|
|
31
|
+
timeZone?: string | undefined;
|
|
32
|
+
startAtMs?: number | undefined;
|
|
22
33
|
}, {
|
|
23
34
|
kind: "interval";
|
|
24
35
|
everyMs: number;
|
|
36
|
+
timeZone?: string | undefined;
|
|
37
|
+
startAtMs?: number | undefined;
|
|
38
|
+
}>, z.ZodObject<{
|
|
39
|
+
kind: z.ZodLiteral<"calendar">;
|
|
40
|
+
calendar: z.ZodDiscriminatedUnion<"frequency", [z.ZodObject<{
|
|
41
|
+
time: z.ZodString;
|
|
42
|
+
timeZone: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
43
|
+
frequency: z.ZodLiteral<"daily">;
|
|
44
|
+
}, "strict", z.ZodTypeAny, {
|
|
45
|
+
time: string;
|
|
46
|
+
frequency: "daily";
|
|
47
|
+
timeZone: string;
|
|
48
|
+
}, {
|
|
49
|
+
time: string;
|
|
50
|
+
frequency: "daily";
|
|
51
|
+
timeZone: string;
|
|
52
|
+
}>, z.ZodObject<{
|
|
53
|
+
weekdays: z.ZodEffects<z.ZodArray<z.ZodNumber, "many">, number[], number[]>;
|
|
54
|
+
time: z.ZodString;
|
|
55
|
+
timeZone: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
|
|
56
|
+
frequency: z.ZodLiteral<"weekly">;
|
|
57
|
+
}, "strict", z.ZodTypeAny, {
|
|
58
|
+
time: string;
|
|
59
|
+
frequency: "weekly";
|
|
60
|
+
timeZone: string;
|
|
61
|
+
weekdays: number[];
|
|
62
|
+
}, {
|
|
63
|
+
time: string;
|
|
64
|
+
frequency: "weekly";
|
|
65
|
+
timeZone: string;
|
|
66
|
+
weekdays: number[];
|
|
67
|
+
}>]>;
|
|
68
|
+
startAtMs: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
}, "strict", z.ZodTypeAny, {
|
|
70
|
+
kind: "calendar";
|
|
71
|
+
calendar: {
|
|
72
|
+
time: string;
|
|
73
|
+
frequency: "daily";
|
|
74
|
+
timeZone: string;
|
|
75
|
+
} | {
|
|
76
|
+
time: string;
|
|
77
|
+
frequency: "weekly";
|
|
78
|
+
timeZone: string;
|
|
79
|
+
weekdays: number[];
|
|
80
|
+
};
|
|
81
|
+
startAtMs?: number | undefined;
|
|
82
|
+
}, {
|
|
83
|
+
kind: "calendar";
|
|
84
|
+
calendar: {
|
|
85
|
+
time: string;
|
|
86
|
+
frequency: "daily";
|
|
87
|
+
timeZone: string;
|
|
88
|
+
} | {
|
|
89
|
+
time: string;
|
|
90
|
+
frequency: "weekly";
|
|
91
|
+
timeZone: string;
|
|
92
|
+
weekdays: number[];
|
|
93
|
+
};
|
|
94
|
+
startAtMs?: number | undefined;
|
|
25
95
|
}>]>;
|
|
26
96
|
export type TriggerSpec = z.infer<typeof triggerSpecSchema>;
|
|
97
|
+
export declare const scheduleTimingInputSchema: z.ZodEffects<z.ZodObject<{
|
|
98
|
+
every: z.ZodOptional<z.ZodString>;
|
|
99
|
+
calendar: z.ZodOptional<z.ZodDiscriminatedUnion<"frequency", [z.ZodObject<{
|
|
100
|
+
time: z.ZodString;
|
|
101
|
+
frequency: z.ZodLiteral<"daily">;
|
|
102
|
+
} & {
|
|
103
|
+
timeZone: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
104
|
+
}, "strict", z.ZodTypeAny, {
|
|
105
|
+
time: string;
|
|
106
|
+
frequency: "daily";
|
|
107
|
+
timeZone?: string | undefined;
|
|
108
|
+
}, {
|
|
109
|
+
time: string;
|
|
110
|
+
frequency: "daily";
|
|
111
|
+
timeZone?: string | undefined;
|
|
112
|
+
}>, z.ZodObject<{
|
|
113
|
+
weekdays: z.ZodEffects<z.ZodArray<z.ZodNumber, "many">, number[], number[]>;
|
|
114
|
+
time: z.ZodString;
|
|
115
|
+
frequency: z.ZodLiteral<"weekly">;
|
|
116
|
+
} & {
|
|
117
|
+
timeZone: z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
118
|
+
}, "strict", z.ZodTypeAny, {
|
|
119
|
+
time: string;
|
|
120
|
+
frequency: "weekly";
|
|
121
|
+
weekdays: number[];
|
|
122
|
+
timeZone?: string | undefined;
|
|
123
|
+
}, {
|
|
124
|
+
time: string;
|
|
125
|
+
frequency: "weekly";
|
|
126
|
+
weekdays: number[];
|
|
127
|
+
timeZone?: string | undefined;
|
|
128
|
+
}>]>>;
|
|
129
|
+
startAt: z.ZodOptional<z.ZodString>;
|
|
130
|
+
}, "strict", z.ZodTypeAny, {
|
|
131
|
+
every?: string | undefined;
|
|
132
|
+
calendar?: {
|
|
133
|
+
time: string;
|
|
134
|
+
frequency: "daily";
|
|
135
|
+
timeZone?: string | undefined;
|
|
136
|
+
} | {
|
|
137
|
+
time: string;
|
|
138
|
+
frequency: "weekly";
|
|
139
|
+
weekdays: number[];
|
|
140
|
+
timeZone?: string | undefined;
|
|
141
|
+
} | undefined;
|
|
142
|
+
startAt?: string | undefined;
|
|
143
|
+
}, {
|
|
144
|
+
every?: string | undefined;
|
|
145
|
+
calendar?: {
|
|
146
|
+
time: string;
|
|
147
|
+
frequency: "daily";
|
|
148
|
+
timeZone?: string | undefined;
|
|
149
|
+
} | {
|
|
150
|
+
time: string;
|
|
151
|
+
frequency: "weekly";
|
|
152
|
+
weekdays: number[];
|
|
153
|
+
timeZone?: string | undefined;
|
|
154
|
+
} | undefined;
|
|
155
|
+
startAt?: string | undefined;
|
|
156
|
+
}>, {
|
|
157
|
+
every?: string | undefined;
|
|
158
|
+
calendar?: {
|
|
159
|
+
time: string;
|
|
160
|
+
frequency: "daily";
|
|
161
|
+
timeZone?: string | undefined;
|
|
162
|
+
} | {
|
|
163
|
+
time: string;
|
|
164
|
+
frequency: "weekly";
|
|
165
|
+
weekdays: number[];
|
|
166
|
+
timeZone?: string | undefined;
|
|
167
|
+
} | undefined;
|
|
168
|
+
startAt?: string | undefined;
|
|
169
|
+
}, {
|
|
170
|
+
every?: string | undefined;
|
|
171
|
+
calendar?: {
|
|
172
|
+
time: string;
|
|
173
|
+
frequency: "daily";
|
|
174
|
+
timeZone?: string | undefined;
|
|
175
|
+
} | {
|
|
176
|
+
time: string;
|
|
177
|
+
frequency: "weekly";
|
|
178
|
+
weekdays: number[];
|
|
179
|
+
timeZone?: string | undefined;
|
|
180
|
+
} | undefined;
|
|
181
|
+
startAt?: string | undefined;
|
|
182
|
+
}>;
|
|
183
|
+
export type ScheduleTimingInput = z.input<typeof scheduleTimingInputSchema>;
|
|
184
|
+
export declare function createScheduleTrigger(input: ScheduleTimingInput, nowMs?: number): TriggerSpec;
|
|
27
185
|
export declare class ScheduleTriggerError extends Error {
|
|
28
186
|
readonly code: "schedule_trigger_invalid";
|
|
29
187
|
constructor(message: string);
|
|
@@ -32,7 +190,8 @@ export declare function formatDuration(ms: number): string;
|
|
|
32
190
|
export declare function formatInterval(ms: number): string;
|
|
33
191
|
export declare function parseIntervalText(text: string): number;
|
|
34
192
|
export declare function parseMaxRunText(text: string): number;
|
|
35
|
-
export declare function createIntervalTrigger(text: string):
|
|
193
|
+
export declare function createIntervalTrigger(text: string): z.infer<typeof intervalTriggerSchema>;
|
|
36
194
|
export declare function describeTrigger(trigger: TriggerSpec): string;
|
|
37
195
|
export declare function computeNextRunAtMs(trigger: TriggerSpec, nowMs: number): number;
|
|
196
|
+
export declare function computeFirstRunAtMs(trigger: TriggerSpec, nowMs: number): number;
|
|
38
197
|
export declare function parseTriggerJson(json: string): TriggerSpec;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as r}from"zod";import{SCHEDULER_LIMITS as e}from"./limits.js";export const TRIGGER_KINDS={interval:"interval"};export const intervalTriggerSchema=r.object({kind:r.literal(TRIGGER_KINDS.interval),everyMs:r.number().int().min(e.minIntervalMs).max(e.maxIntervalMs)}).strict();export const triggerSpecSchema=r.discriminatedUnion("kind",[intervalTriggerSchema]);export class ScheduleTriggerError extends Error{code="schedule_trigger_invalid";constructor(r){super(r),this.name="ScheduleTriggerError"}}const
|
|
1
|
+
import{z as r}from"zod";import{SCHEDULER_LIMITS as e}from"./limits.js";import{calendarScheduleSchema as t,calendarScheduleInputSchema as n,describeCalendar as a,nextCalendarRunAtMs as i,parseLocalStartAt as s,systemTimeZone as o,timeZoneSchema as c}from"./calendar.js";export const TRIGGER_KINDS={interval:"interval",calendar:"calendar"};export const intervalTriggerSchema=r.object({kind:r.literal(TRIGGER_KINDS.interval),everyMs:r.number().int().min(e.minIntervalMs).max(e.maxIntervalMs),startAtMs:r.number().int().min(0).max(2534022144e5).optional(),timeZone:c.optional()}).strict();const l=r.object({kind:r.literal(TRIGGER_KINDS.calendar),calendar:t,startAtMs:r.number().int().min(0).max(2534022144e5).optional()}).strict();export const triggerSpecSchema=r.discriminatedUnion("kind",[intervalTriggerSchema,l]);export const scheduleTimingInputSchema=r.object({every:r.string().trim().min(1).optional(),calendar:n.optional(),startAt:r.string().trim().min(1).optional()}).strict().refine(r=>void 0===r.every!=(void 0===r.calendar),{message:"every 与 calendar 必须且只能提供一个"});export function createScheduleTrigger(e,t=Date.now()){const n=scheduleTimingInputSchema.safeParse(e);if(!n.success)throw new ScheduleTriggerError(n.error.issues[0]?.message??"定时参数无效");const a=n.data,i=a.calendar?.timeZone??o();let c;if(void 0!==a.startAt){try{c=/(?:Z|[+-]\d{2}:\d{2})$/u.test(a.startAt)?Date.parse(r.string().datetime({offset:!0}).parse(a.startAt)):s(a.startAt,i)}catch(r){throw new ScheduleTriggerError(`startAt 无效:${r instanceof Error?r.message:String(r)}`)}if(!Number.isFinite(c)||c<=t)throw new ScheduleTriggerError("startAt 必须是未来时间")}const l=void 0===c?{}:{startAtMs:c},m=void 0!==a.calendar?{kind:TRIGGER_KINDS.calendar,calendar:{...a.calendar,timeZone:i},...l}:{...createIntervalTrigger(a.every??""),...l,...void 0===c?{}:{timeZone:i}},d=triggerSpecSchema.safeParse(m);if(!d.success)throw new ScheduleTriggerError(d.error.issues[0]?.message??"定时参数无效");return d.data}export class ScheduleTriggerError extends Error{code="schedule_trigger_invalid";constructor(r){super(r),this.name="ScheduleTriggerError"}}const m={s:1e3,m:6e4,h:36e5,d:864e5},d=/^(\d{1,9})([smhd])$/u;function u(r){return Object.hasOwn(m,r)}export function formatDuration(r){return r%m.d===0?`${String(r/m.d)} 天`:r%m.h===0?`${String(r/m.h)} 小时`:r%m.m===0?`${String(r/m.m)} 分钟`:`${String(Math.round(r/m.s))} 秒`}export function formatInterval(r){return`每 ${formatDuration(r)}`}function g(r,e){const t=r.trim(),n=d.exec(t),a=n?.[1],i=n?.[2];if(void 0===a||void 0===i||!u(i))throw new ScheduleTriggerError(`无法识别的${e.label} "${t}":格式为 <数字><s|m|h|d>,例如 30m、2h、1d`);const s=Number.parseInt(a,10);if(s<=0)throw new ScheduleTriggerError(`${e.label}必须大于 0`);const o=s*m[i];if(o<e.minMs)throw new ScheduleTriggerError(`${e.label}不能小于 ${String(e.minMs/m.s)} 秒(收到 ${t})`);if(o>e.maxMs)throw new ScheduleTriggerError(`${e.label}不能大于 ${formatDuration(e.maxMs)}(收到 ${t})`);return o}export function parseIntervalText(r){return g(r,{label:"间隔",minMs:e.minIntervalMs,maxMs:e.maxIntervalMs})}export function parseMaxRunText(r){return g(r,{label:"单次运行上限",minMs:e.minMaxRunMs,maxMs:e.maxRunCeilingMs})}export function createIntervalTrigger(r){return{kind:TRIGGER_KINDS.interval,everyMs:parseIntervalText(r)}}export function describeTrigger(r){const e=r.kind===TRIGGER_KINDS.interval?formatInterval(r.everyMs):a(r.calendar);if(void 0===r.startAtMs)return e;const t=r.kind===TRIGGER_KINDS.calendar?r.calendar.timeZone:r.timeZone??"UTC";return`${e},从 ${new Date(r.startAtMs).toLocaleString("zh-CN",{timeZone:t,hour12:!1})}(${t})开始`}export function computeNextRunAtMs(r,e){return r.kind===TRIGGER_KINDS.interval?Math.max(e+r.everyMs,r.startAtMs??-1/0):i(r.calendar,Math.max(e,(r.startAtMs??0)-1))}export function computeFirstRunAtMs(r,e){if(void 0!==r.startAtMs&&r.startAtMs<=e)throw new ScheduleTriggerError("startAt 必须是未来时间;开始时间已过,请重新创建");return r.kind===TRIGGER_KINDS.interval&&void 0!==r.startAtMs?r.startAtMs:computeNextRunAtMs(r,e)}export function parseTriggerJson(r){let e;try{e=JSON.parse(r)}catch{throw new ScheduleTriggerError("trigger 不是合法 JSON")}const t=triggerSpecSchema.safeParse(e);if(!t.success)throw new ScheduleTriggerError(`trigger 不合法(${t.error.issues[0]?.path.join(".")??""}):${t.error.issues[0]?.message??"unknown"}`);return t.data}
|
|
@@ -193,6 +193,8 @@ export interface CreateScheduleInput {
|
|
|
193
193
|
readonly cwd: string;
|
|
194
194
|
readonly trigger: TriggerSpec;
|
|
195
195
|
readonly fireImmediately?: boolean;
|
|
196
|
+
/** Approval snapshot, checked atomically when inserting a new schedule. */
|
|
197
|
+
readonly expectedFirstRunAtMs?: number;
|
|
196
198
|
readonly authorityDigest?: string;
|
|
197
199
|
readonly maxRunMs?: number;
|
|
198
200
|
readonly maxRounds?: number;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { StopCondition, ToolSet } from "ai";
|
|
2
|
+
/** Local to one inference sequence; never blocks repaired inputs or future user turns. */
|
|
3
|
+
export declare function createInvalidScheduleRetryGuard(): {
|
|
4
|
+
stop: StopCondition<ToolSet>;
|
|
5
|
+
readonly message: string | undefined;
|
|
6
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isDeepStrictEqual as o}from"node:util";import{readToolOutcome as t,TOOL_OUTCOME_KINDS as e}from"./normalize-result.js";import{SCHEDULE_CREATE_TOOL_ID as r}from"./schedule-tool.js";export function createInvalidScheduleRetryGuard(){let n;return{stop:({steps:l})=>{const i=[];for(const u of l)for(const l of u.toolCalls){if(l.toolName!==r)continue;const s=u.toolResults.find(o=>o.toolCallId===l.toolCallId);if(!0===l.invalid||void 0!==s&&t(s.output).kind===e.invalidInput){if(i.some(t=>o(t,l.input)))return n="定时任务参数连续重复出错,已停止本轮自动重试。请按错误提示修正 recurrence;若只指定了开始时间和总轮数,请补充两轮间隔。此前已成功执行的其他操作不会回滚。",!0;i.push(l.input)}}return!1},get message(){return n}}}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ScheduleToolCreateRequest } from "@roll-agent/core/scheduler-host/schedule-tool-binding";
|
|
3
|
+
/** Provider strict mode requires every property; null represents only declared defaults. */
|
|
4
|
+
export declare const scheduleCreateInputSchema: z.ZodObject<{
|
|
5
|
+
name: z.ZodString;
|
|
6
|
+
prompt: z.ZodString;
|
|
7
|
+
recurrence: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
8
|
+
kind: z.ZodLiteral<"interval">;
|
|
9
|
+
every: z.ZodString;
|
|
10
|
+
}, "strict", z.ZodTypeAny, {
|
|
11
|
+
every: string;
|
|
12
|
+
kind: "interval";
|
|
13
|
+
}, {
|
|
14
|
+
every: string;
|
|
15
|
+
kind: "interval";
|
|
16
|
+
}>, z.ZodObject<{
|
|
17
|
+
time: z.ZodString;
|
|
18
|
+
} & {
|
|
19
|
+
kind: z.ZodLiteral<"daily">;
|
|
20
|
+
timeZone: z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
21
|
+
}, "strict", z.ZodTypeAny, {
|
|
22
|
+
time: string;
|
|
23
|
+
kind: "daily";
|
|
24
|
+
timeZone: string | null;
|
|
25
|
+
}, {
|
|
26
|
+
time: string;
|
|
27
|
+
kind: "daily";
|
|
28
|
+
timeZone: string | null;
|
|
29
|
+
}>, z.ZodObject<{
|
|
30
|
+
time: z.ZodString;
|
|
31
|
+
weekdays: z.ZodEffects<z.ZodArray<z.ZodNumber, "many">, number[], number[]>;
|
|
32
|
+
} & {
|
|
33
|
+
kind: z.ZodLiteral<"weekly">;
|
|
34
|
+
timeZone: z.ZodNullable<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
|
|
35
|
+
}, "strict", z.ZodTypeAny, {
|
|
36
|
+
time: string;
|
|
37
|
+
kind: "weekly";
|
|
38
|
+
timeZone: string | null;
|
|
39
|
+
weekdays: number[];
|
|
40
|
+
}, {
|
|
41
|
+
time: string;
|
|
42
|
+
kind: "weekly";
|
|
43
|
+
timeZone: string | null;
|
|
44
|
+
weekdays: number[];
|
|
45
|
+
}>]>;
|
|
46
|
+
startAt: z.ZodNullable<z.ZodString>;
|
|
47
|
+
cwd: z.ZodNullable<z.ZodString>;
|
|
48
|
+
rounds: z.ZodNullable<z.ZodNumber>;
|
|
49
|
+
maxRun: z.ZodNullable<z.ZodString>;
|
|
50
|
+
}, "strict", z.ZodTypeAny, {
|
|
51
|
+
name: string;
|
|
52
|
+
prompt: string;
|
|
53
|
+
cwd: string | null;
|
|
54
|
+
startAt: string | null;
|
|
55
|
+
maxRun: string | null;
|
|
56
|
+
rounds: number | null;
|
|
57
|
+
recurrence: {
|
|
58
|
+
every: string;
|
|
59
|
+
kind: "interval";
|
|
60
|
+
} | {
|
|
61
|
+
time: string;
|
|
62
|
+
kind: "daily";
|
|
63
|
+
timeZone: string | null;
|
|
64
|
+
} | {
|
|
65
|
+
time: string;
|
|
66
|
+
kind: "weekly";
|
|
67
|
+
timeZone: string | null;
|
|
68
|
+
weekdays: number[];
|
|
69
|
+
};
|
|
70
|
+
}, {
|
|
71
|
+
name: string;
|
|
72
|
+
prompt: string;
|
|
73
|
+
cwd: string | null;
|
|
74
|
+
startAt: string | null;
|
|
75
|
+
maxRun: string | null;
|
|
76
|
+
rounds: number | null;
|
|
77
|
+
recurrence: {
|
|
78
|
+
every: string;
|
|
79
|
+
kind: "interval";
|
|
80
|
+
} | {
|
|
81
|
+
time: string;
|
|
82
|
+
kind: "daily";
|
|
83
|
+
timeZone: string | null;
|
|
84
|
+
} | {
|
|
85
|
+
time: string;
|
|
86
|
+
kind: "weekly";
|
|
87
|
+
timeZone: string | null;
|
|
88
|
+
weekdays: number[];
|
|
89
|
+
};
|
|
90
|
+
}>;
|
|
91
|
+
export declare function toScheduleCreateRequest(input: z.output<typeof scheduleCreateInputSchema>): ScheduleToolCreateRequest;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as e}from"zod";import{calendarScheduleSchema as n,timeZoneSchema as t}from"../scheduler/calendar.js";const r=e.object({kind:e.literal("interval"),every:e.string().trim().min(1).describe("两轮间隔,如 1m、30m(60s..365d);用户未指定时先询问,不能猜测")}).strict(),i=n.options[0].omit({frequency:!0}).extend({kind:e.literal("daily"),timeZone:t.nullable().describe("IANA 时区;null 使用并保存运行 Roll 的机器时区")}),l=n.options[1].omit({frequency:!0}).extend({kind:e.literal("weekly"),timeZone:i.shape.timeZone});export const scheduleCreateInputSchema=e.object({name:e.string().trim().min(1).max(120).describe("任务名称"),prompt:e.string().trim().min(1).max(4e3).describe("每轮执行的工作;不要把触发时间或停止条件只写在 prompt 中"),recurrence:e.discriminatedUnion("kind",[r,i,l]).describe("重复规则:interval=固定间隔,daily=每天,weekly=每周。今天/明天某时只指定 startAt,不代表 daily。缺少两轮间隔时先询问用户"),startAt:e.string().trim().min(1).nullable().describe("未来开始时间 YYYY-MM-DDTHH:mm 或带偏移 ISO;null 不指定。interval 首轮在此时执行,daily/weekly 在此时起找匹配日期;不是重复规则"),cwd:e.string().nullable().describe("执行工作目录;null 使用当前会话目录"),rounds:e.number().int().positive().max(Number.MAX_SAFE_INTEGER).nullable().describe("总自动轮数;null 不限。失败、取消、空结果占轮数;同轮重试和手动运行不额外计数"),maxRun:e.string().nullable().describe("单轮时长上限,如 1h(60s..24h);null 使用默认 1 小时")}).strict();export function toScheduleCreateRequest(e){const{recurrence:n,startAt:t,cwd:r,rounds:i,maxRun:l,name:m,prompt:a}=e,s={name:m,prompt:a,...null===t?{}:{startAt:t},...null===r?{}:{cwd:r},...null===i?{}:{rounds:i},...null===l?{}:{maxRun:l}};if("interval"===n.kind)return{...s,every:n.every};const d={time:n.time,...null===n.timeZone?{}:{timeZone:n.timeZone}};return{...s,calendar:"daily"===n.kind?{frequency:"daily",...d}:{frequency:"weekly",...d,weekdays:n.weekdays}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{tool as e}from"ai";import{z as t}from"zod";import{buildScheduleExtendTools as r}from"./schedule-extend-tool.js";import{SCHEDULE_STATUSES as n}from"../scheduler/types.js";import{
|
|
1
|
+
import{tool as e}from"ai";import{z as t}from"zod";import{buildScheduleExtendTools as r}from"./schedule-extend-tool.js";import{SCHEDULE_STATUSES as n}from"../scheduler/types.js";import{systemTimeZone as i}from"../scheduler/calendar.js";import{computeNextRunAtMs as o}from"../scheduler/trigger.js";import{scheduleCreateInputSchema as s,toScheduleCreateRequest as a}from"./schedule-create-input.js";import{gateToolCall as u}from"./build-tools.js";import{TOOL_OUTCOME_KINDS as c,failedToolResult as l,successfulToolResult as d,toolResultToModelOutput as m}from"./normalize-result.js";import{TOOL_RESOURCE_ACCESS_MODES as p,executeCoordinatedTool as g}from"./tool-execution-coordinator.js";export const SCHEDULE_TOOL_AGENT_NAME="roll";export const SCHEDULE_CREATE_TOOL_NAME="schedule_create";export const SCHEDULE_LIST_TOOL_NAME="schedule_list";export const SCHEDULE_CREATE_TOOL_ID="roll__schedule_create";export const SCHEDULE_LIST_TOOL_ID="roll__schedule_list";const $=t.object({status:t.enum(["all",...Object.values(n)]).optional().describe("按状态过滤,省略时返回全部"),offset:t.number().int().min(0).optional().describe("分页偏移,默认 0"),limit:t.number().int().min(1).max(100).optional().describe("最多返回条数,默认 50")}),f=Symbol("schedule-invalid-input");function h(e){return"object"==typeof e&&null!==e&&e.kind===f}function _(e){return"object"==typeof e&&null!==e&&!1===e.ok}function x(e){const t="invalid_input"===e.code||"schedule_invalid"===e.code||"schedule_trigger_invalid"===e.code?c.invalidInput:c.toolFailed;return l(t,e.message,{raw:e})}function y(e){return 0===e.warnings.length?"":`\n${e.warnings.map(e=>`注意:${e.message}。`).join("\n")}`}function v(e){const t="calendar"===e.trigger.kind?e.trigger.calendar.timeZone:e.trigger.timeZone??i();return{name:e.name,prompt:e.prompt,every:e.everyDisplay,recurrence:e.everyDisplay,cwd:e.cwd,maxRun:e.maxRunDisplay,firstRunAt:E(e.firstRunAt,t),firstRunAtIso:e.firstRunAt,timeZone:t,...1===e.maxRounds?{}:{nextRunAtEstimate:E(new Date(o(e.trigger,Date.parse(e.firstRunAt))).toISOString(),t)},timingSemantics:"interval"===e.trigger.kind?"第二轮时间仅为预计;按每轮实际领取时间加间隔计算,延迟领取时顺延,不固定每天执行":"按保存的时区和日历规则匹配;跳时日期跳过,重复钟点仅执行较早一次",rounds:void 0===e.maxRounds?"不限轮数":`最多自动执行 ${String(e.maxRounds)} 轮`,lifecycle:void 0===e.maxRounds?"会持续运行,直到暂停或删除;创建时记录当前权限边界":"达到轮数上限后,最后一轮执行、重试及清场结算完毕自动结束;创建时记录当前权限边界",...e.readiness.warnings.length>0?{serviceStatus:e.readiness.warnings.map(e=>e.message).join(";")}:{}}}function E(e,t=i()){const r=new Date(e);return Number.isNaN(r.getTime())?e:r.toLocaleString("zh-CN",{timeZone:t,hour12:!1})}export function buildScheduleToolset(t,n,o){const S=t.includeCreate??!0,R=S?n.register("roll","schedule_create"):void 0,j=n.register("roll","schedule_list"),A={captureExecutionState:e=>{const r=s.safeParse(e);return r.success?t.port.captureCreate(a(r.data),t.sessionCwd):{kind:f,message:`参数校验失败: ${r.error.issues.map(e=>`${e.path.join(".")||"input"}: ${e.message}`).join("; ")}。使用唯一 recurrence 分支;今天/明天某时填写 startAt,缺少两轮间隔先询问用户。缺省字段填写 null。不要原样重试相同参数。`}},prepare:async(e,t)=>{if(h(t))return l(c.invalidInput,t.message);if(_(t))return x(t);const r=t;return u(o,"roll","schedule_create",v(r),void 0,{explanation:`将登记定时任务「${r.name}」(${r.everyDisplay})`})},resources:()=>[{key:"schedule-ledger",mode:p.write}]};void 0!==R&&o.coordinator?.register(R,A);const w={prepare:async e=>u(o,"roll","schedule_list",e??{},{readOnlyHint:!0}),resources:()=>[{key:"schedule-ledger",mode:p.read}]};o.coordinator?.register(j,w);const D=void 0===R?{}:{[R]:e({description:"登记定时任务,每轮无人值守 chat 执行 prompt。startAt=开始时间,recurrence=重复规则,rounds=总轮数,三个维度独立。今天/明天某时不是 daily;缺少两轮间隔先澄清,不能猜成每天一次。信息齐全后只做工具自带的完整参数确认,不重复口头确认。可选值用 null 表示缺省。不支持 cron 或每天开启一组多轮循环。",inputSchema:s,strict:!0,toModelOutput:({output:e})=>m(e),execute:async(e,r)=>g(o.coordinator,A,R,r.toolCallId,e,r.abortSignal,async e=>{if(h(e))return l(c.invalidInput,e.message);if(_(e))return x(e);const r=e,n=await t.port.create(r);if(_(n))return x(n);const o=n.schedule,s="calendar"===o.trigger.spec?.kind?o.trigger.spec.calendar.timeZone:o.trigger.spec?.timeZone??i(),a=n.created?`已登记定时任务 "${o.name}"(${o.trigger.display},单次上限 ${o.maxRun.display})。`:n.reauthorized?`已存在相同定义的任务 "${o.name}"(id ${o.id}),未重复创建;已按当前权限边界重新授权。`:`已存在相同定义的任务 "${o.name}"(id ${o.id}),未重复创建。`,u=void 0===o.nextRunAt?"":`下次运行约 ${E(o.nextRunAt,s)}(${s})。`,m=y(n.readiness)||(n.readiness.automaticRunsReady?"":"\n注意:调度服务未就绪,任务不会自动执行。");return d(`${a}${null===o.rounds.max?"":`最多自动执行 ${String(o.rounds.max)} 轮。`}${o.roundsDisplay}。${u}${m}`,{raw:n})})})},b={[j]:e({description:"列出当前配置下已登记的定时任务(含状态、频率、下次运行时间与最近错误摘要)。创建前可用它确认是否已有同类任务。",inputSchema:$,toModelOutput:({output:e})=>m(e),execute:async(e,r)=>g(o.coordinator,w,j,r.toolCallId,e,r.abortSignal,async()=>{const r=$.safeParse(e??{});if(!r.success)return l(c.invalidInput,`参数校验失败: ${r.error.issues.map(e=>e.message).join("; ")}`);const n=await t.port.list(r.data,t.sessionCwd);if(_(n))return x(n);if(0===n.total)return d(`暂无定时任务。${y(n.readiness)}`.trim(),{raw:n});const o=n.schedules.map(e=>{const t="active"===e.status&&void 0!==e.nextRunAt?`,下次 ${E(e.nextRunAt,e.timeZone)}(${e.timeZone??i()})`:"",r=void 0===e.lastError?"":`,最近错误:${e.lastError}`;return`- ${e.name}(${e.status},${e.trigger},${e.roundsDisplay}${t})id=${e.id}\n 内容:${e.promptExcerpt}${r}`}),s=n.hasMore?`\n共 ${String(n.total)} 个,仅显示 ${String(n.schedules.length)} 个;用 offset/limit 翻页。`:"";return d(`${o.join("\n")}${s}${y(n.readiness)}`,{raw:n})})})};return{createTools:D,extendTools:S?r(t,n,o):{},listTools:b}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@roll-agent/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"zod": "^3.25.76"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@roll-agent/core": "0.
|
|
38
|
+
"@roll-agent/core": "0.40.0",
|
|
39
39
|
"@types/node": "^22.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|