@myagentroam/node 0.9.128 → 0.9.129
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/connector.js
CHANGED
|
@@ -1334,7 +1334,7 @@ export class NodeConnector {
|
|
|
1334
1334
|
session.workspaceId !== task.workspaceId ||
|
|
1335
1335
|
session.runner !== task.runner)
|
|
1336
1336
|
throw new Error('SCHEDULE_SESSION_NOT_FOUND');
|
|
1337
|
-
const
|
|
1337
|
+
const configuredSession = this.nativeSessionProjectionService.ensureResumedConfiguration(session);
|
|
1338
1338
|
return this.scheduledRunAuthorization.authorize({
|
|
1339
1339
|
taskId: task.id,
|
|
1340
1340
|
revision: task.revision,
|
|
@@ -1343,7 +1343,7 @@ export class NodeConnector {
|
|
|
1343
1343
|
workspaceId: task.workspaceId,
|
|
1344
1344
|
ownerUserId: task.ownerUserId,
|
|
1345
1345
|
runner: task.runner,
|
|
1346
|
-
model:
|
|
1346
|
+
model: configuredSession.model
|
|
1347
1347
|
});
|
|
1348
1348
|
},
|
|
1349
1349
|
submit: async (task, occurrenceId, context) => {
|
|
@@ -98,31 +98,33 @@ export class NativeSessionProjectionService {
|
|
|
98
98
|
externalSessionId: direct.externalSessionId,
|
|
99
99
|
nativeControl: 'EXTERNAL',
|
|
100
100
|
cwd: direct.cwd,
|
|
101
|
+
...(direct.model === null ? {} : { model: direct.model }),
|
|
102
|
+
...(direct.effort === null ? {} : { effort: direct.effort }),
|
|
103
|
+
...(direct.access === null ? {} : { access: direct.access }),
|
|
101
104
|
...(direct.runnerTitle === null ? {} : { title: direct.runnerTitle }),
|
|
102
105
|
...(direct.customTitle === null ? {} : { customTitle: direct.customTitle })
|
|
103
106
|
});
|
|
104
107
|
}
|
|
105
108
|
resumedConfiguration(session) {
|
|
106
109
|
const workspace = this.options.database()?.getWorkspace(session.workspaceId);
|
|
107
|
-
const current = {
|
|
108
|
-
runner: session.runner,
|
|
109
|
-
model: session.model,
|
|
110
|
-
effort: session.effort,
|
|
111
|
-
access: session.access
|
|
112
|
-
};
|
|
113
|
-
if (typeof current.model === 'string' &&
|
|
114
|
-
typeof current.effort === 'string' &&
|
|
115
|
-
typeof current.access === 'string')
|
|
116
|
-
return session.runner === 'mar-agent'
|
|
117
|
-
? { ...current, access: 'full-access' }
|
|
118
|
-
: current;
|
|
119
110
|
const saved = this.options
|
|
120
111
|
.database()
|
|
121
112
|
?.getRunnerDefaults()
|
|
122
113
|
.find((value) => value.runner === session.runner);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
114
|
+
const fallback = saved ?? this.options.runners.require(session.runner).defaultConfiguration(workspace);
|
|
115
|
+
const configuration = {
|
|
116
|
+
runner: session.runner,
|
|
117
|
+
model: typeof session.model === 'string' && session.model.trim().length > 0
|
|
118
|
+
? session.model
|
|
119
|
+
: fallback.model,
|
|
120
|
+
effort: typeof session.effort === 'string' ? session.effort : fallback.effort,
|
|
121
|
+
access: typeof session.access === 'string' && session.access.trim().length > 0
|
|
122
|
+
? session.access
|
|
123
|
+
: fallback.access
|
|
124
|
+
};
|
|
125
|
+
return session.runner === 'mar-agent'
|
|
126
|
+
? { ...configuration, access: 'full-access' }
|
|
127
|
+
: configuration;
|
|
126
128
|
}
|
|
127
129
|
ensureResumedConfiguration(session) {
|
|
128
130
|
const configuration = this.resumedConfiguration(session);
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
export function parseScheduledCron(cron) {
|
|
2
|
-
const
|
|
3
|
-
if (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
const parsed = parseCronExpression(cron);
|
|
3
|
+
if (parsed.dayOfMonthWildcard &&
|
|
4
|
+
parsed.monthWildcard &&
|
|
5
|
+
/^\d+$/.test(parsed.fields[0] ?? '') &&
|
|
6
|
+
(parsed.fields[1] === '*' || /^\d+$/.test(parsed.fields[1] ?? '')) &&
|
|
7
|
+
(parsed.fields[4] === '*' || /^\d+$/.test(parsed.fields[4] ?? ''))) {
|
|
8
|
+
const minute = exactInteger(parsed.fields[0], 0, 59);
|
|
9
|
+
const hour = parsed.fields[1] === '*' ? undefined : exactInteger(parsed.fields[1], 0, 23);
|
|
10
|
+
const weekdayValue = parsed.fields[4] === '*' ? undefined : exactInteger(parsed.fields[4], 0, 7);
|
|
11
|
+
if (hour === undefined && weekdayValue === undefined)
|
|
12
|
+
return { kind: 'HOURLY', minute };
|
|
13
|
+
if (hour !== undefined && weekdayValue === undefined)
|
|
14
|
+
return { kind: 'DAILY', minute, hour };
|
|
15
|
+
if (hour !== undefined && weekdayValue !== undefined)
|
|
16
|
+
return { kind: 'WEEKLY', minute, hour, weekday: weekdayValue === 7 ? 0 : weekdayValue };
|
|
17
|
+
}
|
|
18
|
+
return { kind: 'CRON', expression: parsed.expression };
|
|
12
19
|
}
|
|
13
20
|
export function assertScheduleTimezone(timezone) {
|
|
14
21
|
if (timezone.length < 1 || timezone.length > 128)
|
|
@@ -21,7 +28,7 @@ export function assertScheduleTimezone(timezone) {
|
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
export function nextScheduledAt(cron, timezone, after) {
|
|
24
|
-
const
|
|
31
|
+
const schedule = parseCronExpression(cron);
|
|
25
32
|
assertScheduleTimezone(timezone);
|
|
26
33
|
if (!Number.isSafeInteger(after) || after < 0)
|
|
27
34
|
throw new Error('SCHEDULE_TIME_INVALID');
|
|
@@ -37,17 +44,81 @@ export function nextScheduledAt(cron, timezone, after) {
|
|
|
37
44
|
});
|
|
38
45
|
const previousKey = localKey(formatter, after);
|
|
39
46
|
let candidate = Math.floor(after / 60_000) * 60_000 + 60_000;
|
|
40
|
-
for (let index = 0; index < 8 * 24 * 60
|
|
47
|
+
for (let index = 0; index < 8 * 366 * 24 * 60; index++, candidate += 60_000) {
|
|
41
48
|
const local = localParts(formatter, candidate);
|
|
42
|
-
if (local
|
|
43
|
-
(cadence.kind === 'HOURLY' || local.hour === cadence.hour) &&
|
|
44
|
-
(cadence.kind !== 'WEEKLY' || local.weekday === cadence.weekday) &&
|
|
45
|
-
local.key !== previousKey)
|
|
49
|
+
if (matches(schedule, local) && local.key !== previousKey)
|
|
46
50
|
return candidate;
|
|
47
51
|
}
|
|
48
52
|
throw new Error('SCHEDULE_NEXT_TIME_UNAVAILABLE');
|
|
49
53
|
}
|
|
50
|
-
function
|
|
54
|
+
function parseCronExpression(cron) {
|
|
55
|
+
const expression = cron.trim();
|
|
56
|
+
const fields = expression.split(/\s+/);
|
|
57
|
+
if (expression.length === 0 ||
|
|
58
|
+
expression.length > 64 ||
|
|
59
|
+
fields.length !== 5 ||
|
|
60
|
+
fields.some((field) => field.length === 0))
|
|
61
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
62
|
+
const minute = parseField(fields[0] ?? '', 0, 59);
|
|
63
|
+
const hour = parseField(fields[1] ?? '', 0, 23);
|
|
64
|
+
const dayOfMonth = parseField(fields[2] ?? '', 1, 31);
|
|
65
|
+
const month = parseField(fields[3] ?? '', 1, 12);
|
|
66
|
+
const dayOfWeek = parseField(fields[4] ?? '', 0, 7, (value) => (value === 7 ? 0 : value));
|
|
67
|
+
return {
|
|
68
|
+
expression,
|
|
69
|
+
fields,
|
|
70
|
+
minute: minute.values,
|
|
71
|
+
hour: hour.values,
|
|
72
|
+
dayOfMonth: dayOfMonth.values,
|
|
73
|
+
month: month.values,
|
|
74
|
+
dayOfWeek: dayOfWeek.values,
|
|
75
|
+
dayOfMonthWildcard: minuteWildcard(dayOfMonth.values, 1, 31),
|
|
76
|
+
monthWildcard: minuteWildcard(month.values, 1, 12),
|
|
77
|
+
dayOfWeekWildcard: minuteWildcard(dayOfWeek.values, 0, 6)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function parseField(field, min, max, normalize = (value) => value) {
|
|
81
|
+
if (field.includes('?'))
|
|
82
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
83
|
+
const values = new Set();
|
|
84
|
+
for (const segment of field.split(',')) {
|
|
85
|
+
if (segment.length === 0)
|
|
86
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
87
|
+
const parts = segment.split('/');
|
|
88
|
+
if (parts.length > 2 || parts.some((part) => part.length === 0))
|
|
89
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
90
|
+
const base = parts[0] ?? '';
|
|
91
|
+
const step = parts[1] === undefined ? 1 : exactInteger(parts[1], 1, max - min + 1);
|
|
92
|
+
let start;
|
|
93
|
+
let end;
|
|
94
|
+
if (base === '*') {
|
|
95
|
+
start = min;
|
|
96
|
+
end = max;
|
|
97
|
+
}
|
|
98
|
+
else if (/^\d+-\d+$/.test(base)) {
|
|
99
|
+
const range = base.split('-');
|
|
100
|
+
start = exactInteger(range[0], min, max);
|
|
101
|
+
end = exactInteger(range[1], min, max);
|
|
102
|
+
if (start > end)
|
|
103
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
104
|
+
}
|
|
105
|
+
else if (parts.length === 1 && /^\d+$/.test(base)) {
|
|
106
|
+
start = exactInteger(base, min, max);
|
|
107
|
+
end = start;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
111
|
+
}
|
|
112
|
+
if (parts[1] !== undefined && start === end)
|
|
113
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
114
|
+
for (let value = start; value <= end; value += step)
|
|
115
|
+
values.add(normalize(value));
|
|
116
|
+
}
|
|
117
|
+
if (values.size === 0)
|
|
118
|
+
throw new Error('SCHEDULE_CRON_INVALID');
|
|
119
|
+
return { values };
|
|
120
|
+
}
|
|
121
|
+
function exactInteger(value, min, max) {
|
|
51
122
|
if (value === undefined || !/^(0|[1-9][0-9]*)$/.test(value))
|
|
52
123
|
throw new Error('SCHEDULE_CRON_INVALID');
|
|
53
124
|
const number = Number(value);
|
|
@@ -55,18 +126,41 @@ function boundedInteger(value, min, max) {
|
|
|
55
126
|
throw new Error('SCHEDULE_CRON_INVALID');
|
|
56
127
|
return number;
|
|
57
128
|
}
|
|
129
|
+
function minuteWildcard(values, min, max) {
|
|
130
|
+
return values.size === max - min + 1;
|
|
131
|
+
}
|
|
58
132
|
function localParts(formatter, time) {
|
|
59
133
|
const fields = Object.fromEntries(formatter.formatToParts(time).map((part) => [part.type, part.value]));
|
|
60
134
|
const hour = Number(fields['hour']);
|
|
61
135
|
const minute = Number(fields['minute']);
|
|
136
|
+
const day = Number(fields['day']);
|
|
137
|
+
const month = Number(fields['month']);
|
|
62
138
|
const weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].indexOf(fields['weekday'] ?? '');
|
|
63
139
|
return {
|
|
64
140
|
hour,
|
|
65
141
|
minute,
|
|
142
|
+
day,
|
|
143
|
+
month,
|
|
66
144
|
weekday,
|
|
67
145
|
key: `${fields['year']}-${fields['month']}-${fields['day']}T${fields['hour']}:${fields['minute']}`
|
|
68
146
|
};
|
|
69
147
|
}
|
|
148
|
+
function matches(schedule, local) {
|
|
149
|
+
if (!schedule.minute.has(local.minute) ||
|
|
150
|
+
!schedule.hour.has(local.hour) ||
|
|
151
|
+
!schedule.month.has(local.month))
|
|
152
|
+
return false;
|
|
153
|
+
const dayOfMonthMatches = schedule.dayOfMonth.has(local.day);
|
|
154
|
+
const dayOfWeekMatches = schedule.dayOfWeek.has(local.weekday);
|
|
155
|
+
const dayMatches = schedule.dayOfMonthWildcard && schedule.dayOfWeekWildcard
|
|
156
|
+
? true
|
|
157
|
+
: schedule.dayOfMonthWildcard
|
|
158
|
+
? dayOfWeekMatches
|
|
159
|
+
: schedule.dayOfWeekWildcard
|
|
160
|
+
? dayOfMonthMatches
|
|
161
|
+
: dayOfMonthMatches || dayOfWeekMatches;
|
|
162
|
+
return dayMatches;
|
|
163
|
+
}
|
|
70
164
|
function localKey(formatter, time) {
|
|
71
165
|
return localParts(formatter, time).key;
|
|
72
166
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.129",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"npm": "11.12.1",
|
|
31
31
|
"ws": "^8.21.3",
|
|
32
32
|
"zod": "4.4.3",
|
|
33
|
-
"@myagentroam/agent": "0.9.
|
|
34
|
-
"@myagentroam/protocol": "0.9.
|
|
35
|
-
"@myagentroam/code-navigation": "0.9.
|
|
33
|
+
"@myagentroam/agent": "0.9.129",
|
|
34
|
+
"@myagentroam/protocol": "0.9.129",
|
|
35
|
+
"@myagentroam/code-navigation": "0.9.129"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/ws": "^8.18.1"
|