@qilin-agent/schedule 3.1.5 → 3.1.6
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/README.i18n.yaml +12 -12
- package/README.md +5 -4
- package/README.zh.md +5 -4
- package/lib/index.js +36 -5
- package/lib/typert.host.js +424 -296
- package/lib/typert.remote-client.d.ts +9 -2
- package/lib/typert.remote-client.js +415 -292
- package/lib/types/domain.d.ts +3 -3
- package/lib/types/domain.js +1 -1
- package/lib/types/index.d.ts +23 -3
- package/lib/types/index.js +39 -4
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +36 -32
package/lib/types/domain.d.ts
CHANGED
|
@@ -31,17 +31,17 @@ export declare class ScheduleLogError extends Error {
|
|
|
31
31
|
*/
|
|
32
32
|
constructor(message: string);
|
|
33
33
|
}
|
|
34
|
-
/** Error from a model-supplied Schedule rule that cannot become a record. */
|
|
34
|
+
/** Error from a model-supplied Schedule rule or target Session that cannot become a record. */
|
|
35
35
|
export declare class ScheduleInputError extends Error {
|
|
36
36
|
/** Stable public Schedule input code. */
|
|
37
|
-
readonly code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high';
|
|
37
|
+
readonly code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'subagent_session';
|
|
38
38
|
/**
|
|
39
39
|
* Construct a stable input failure.
|
|
40
40
|
* @param code - Public Schedule error discriminator.
|
|
41
41
|
* @param message - Stable public diagnostic.
|
|
42
42
|
* @param options - Optional contained implementation cause.
|
|
43
43
|
*/
|
|
44
|
-
constructor(code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high', message: string, options?: ErrorOptions);
|
|
44
|
+
constructor(code: 'invalid_prompt' | 'invalid_selector' | 'invalid_rule' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'subagent_session', message: string, options?: ErrorOptions);
|
|
45
45
|
}
|
|
46
46
|
/** Pure replay result, retaining active create order and every used id. */
|
|
47
47
|
export interface FoldedSchedules {
|
package/lib/types/domain.js
CHANGED
|
@@ -44,7 +44,7 @@ export class ScheduleLogError extends Error {
|
|
|
44
44
|
this.name = 'ScheduleLogError';
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
/** Error from a model-supplied Schedule rule that cannot become a record. */
|
|
47
|
+
/** Error from a model-supplied Schedule rule or target Session that cannot become a record. */
|
|
48
48
|
export class ScheduleInputError extends Error {
|
|
49
49
|
/** Stable public Schedule input code. */
|
|
50
50
|
code;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
56
56
|
*
|
|
57
57
|
* The request must supply a title; a missing, blank-after-trim, or over-long
|
|
58
58
|
* title rejects with `invalid_prompt` instead of deriving one from the prompt.
|
|
59
|
+
* A Session a delegated child owns rejects with `subagent_session`, because delivery
|
|
60
|
+
* can never reach it: the child is one whose delegation depth is above zero.
|
|
59
61
|
* The record is built from the clock reading taken before the request joins the
|
|
60
62
|
* serialized queue, so a create that waits behind a longer operation keeps its
|
|
61
63
|
* request-time anchor and may already be due when the queue reaches it.
|
|
@@ -90,7 +92,9 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
90
92
|
* Delete one task belonging to the selected Session, leaving queued messages intact.
|
|
91
93
|
*
|
|
92
94
|
* The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its
|
|
93
|
-
* saved delivery records go with it.
|
|
95
|
+
* saved delivery records go with it. A task bound to a Session a delegated child owns
|
|
96
|
+
* stays deletable even though creation and timing edits refuse that binding, so a task
|
|
97
|
+
* stored before that rule existed remains removable.
|
|
94
98
|
* @param request - Session and exact task identity.
|
|
95
99
|
* @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.
|
|
96
100
|
* @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.
|
|
@@ -101,10 +105,13 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
101
105
|
* binding without activating the Session or changing saved deliveries.
|
|
102
106
|
*
|
|
103
107
|
* Each supplied field replaces its stored value; an omitted field keeps it. A name or
|
|
104
|
-
* instruction change alone does not reset the committed target.
|
|
108
|
+
* instruction change alone does not reset the committed target. A Session a delegated
|
|
109
|
+
* child owns returns the non-mutating `subagent_session` result, so an edit cannot
|
|
110
|
+
* re-arm a task bound to a Session delivery can never reach, and the Web editor can
|
|
111
|
+
* explain the refusal through the ordinary result it already renders.
|
|
105
112
|
* @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.
|
|
106
113
|
* @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.
|
|
107
|
-
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict result.
|
|
114
|
+
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict/refusal result.
|
|
108
115
|
* Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.
|
|
109
116
|
*/
|
|
110
117
|
update(request: ScheduleUpdateRequest, signal?: AbortSignal): Promise<ScheduleUpdateResult>;
|
|
@@ -116,6 +123,19 @@ export declare class ScheduleService extends TypertRemoteService {
|
|
|
116
123
|
*/
|
|
117
124
|
private emitChanged;
|
|
118
125
|
private getDomain;
|
|
126
|
+
/**
|
|
127
|
+
* Refuse a Session no delivery can reach because a delegated child owns it.
|
|
128
|
+
*
|
|
129
|
+
* Delivery resolves the bound Session through `ctx.sessionController.resolveAgent`,
|
|
130
|
+
* which rejects the live Agent of a delegated child; a stored task for such a Session
|
|
131
|
+
* would stay permanently overdue and retry on every drive. Both operations that can
|
|
132
|
+
* arm a delivery read that same fact here instead of restating it: a delegated child
|
|
133
|
+
* is one whose {@link delegationDepthOf} is above zero, the accounting the delegation
|
|
134
|
+
* cap itself enforces, which survives a cold resume through the persisted header.
|
|
135
|
+
* @param sessionId - Session the task would be bound to.
|
|
136
|
+
* @returns The stable refusal for a delegated child's Session, or undefined when the Session is eligible.
|
|
137
|
+
*/
|
|
138
|
+
private reminderTargetRefusal;
|
|
119
139
|
/**
|
|
120
140
|
* Remove every active task stored for one Session, inside the queue the tools
|
|
121
141
|
* use.
|
package/lib/types/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
37
37
|
import z from '@qilin-agent/schemastery';
|
|
38
38
|
import { Service } from '@qilin-agent/kylin';
|
|
39
39
|
import { TypertRemoteService, Remote } from '@qilin-agent/typert-protocol';
|
|
40
|
+
import { delegationDepthOf } from '@qilin-agent/subagent';
|
|
40
41
|
import { ScheduleRuntime } from "./runtime.js";
|
|
41
42
|
import { scheduleDomain } from "./storage.js";
|
|
42
43
|
import { deliveryHistoryPage } from "./delivery-history.js";
|
|
@@ -79,7 +80,7 @@ let ScheduleService = (() => {
|
|
|
79
80
|
__esDecorate(this, null, _update_decorators, { kind: "method", name: "update", static: false, private: false, access: { has: obj => "update" in obj, get: obj => obj.update }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
80
81
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
81
82
|
}
|
|
82
|
-
static inject = ['agents', 'sessions', '
|
|
83
|
+
static inject = ['agents', 'sessions', 'storageDomain', 'sessionController', 'sessionPersistence'];
|
|
83
84
|
static Config = z.object({
|
|
84
85
|
deliveryHistoryDays: z.number().step(1).min(1).max(3650).default(DEFAULT_DELIVERY_HISTORY_DAYS),
|
|
85
86
|
deliveryHistoryRecords: z.number().step(1).min(1).max(10_000).default(DEFAULT_DELIVERY_HISTORY_RECORDS),
|
|
@@ -193,6 +194,8 @@ let ScheduleService = (() => {
|
|
|
193
194
|
*
|
|
194
195
|
* The request must supply a title; a missing, blank-after-trim, or over-long
|
|
195
196
|
* title rejects with `invalid_prompt` instead of deriving one from the prompt.
|
|
197
|
+
* A Session a delegated child owns rejects with `subagent_session`, because delivery
|
|
198
|
+
* can never reach it: the child is one whose delegation depth is above zero.
|
|
196
199
|
* The record is built from the clock reading taken before the request joins the
|
|
197
200
|
* serialized queue, so a create that waits behind a longer operation keeps its
|
|
198
201
|
* request-time anchor and may already be due when the queue reaches it.
|
|
@@ -229,6 +232,9 @@ let ScheduleService = (() => {
|
|
|
229
232
|
else
|
|
230
233
|
throw new ScheduleInputError('invalid_selector', 'Exactly one reminder selector is required.');
|
|
231
234
|
return this.serialize(async () => {
|
|
235
|
+
const refusal = this.reminderTargetRefusal(sessionId);
|
|
236
|
+
if (refusal !== undefined)
|
|
237
|
+
throw new ScheduleInputError('subagent_session', refusal.message);
|
|
232
238
|
const domain = await this.getDomain();
|
|
233
239
|
signal?.throwIfAborted();
|
|
234
240
|
await domain.table('tasks').put(id, {
|
|
@@ -286,7 +292,9 @@ let ScheduleService = (() => {
|
|
|
286
292
|
* Delete one task belonging to the selected Session, leaving queued messages intact.
|
|
287
293
|
*
|
|
288
294
|
* The row is removed: the task no longer schedules, leaves `list` and `catalog`, and its
|
|
289
|
-
* saved delivery records go with it.
|
|
295
|
+
* saved delivery records go with it. A task bound to a Session a delegated child owns
|
|
296
|
+
* stays deletable even though creation and timing edits refuse that binding, so a task
|
|
297
|
+
* stored before that rule existed remains removable.
|
|
290
298
|
* @param request - Session and exact task identity.
|
|
291
299
|
* @param signal - Optional cancellation checked before persistence begins, including after FIFO waits.
|
|
292
300
|
* @returns Whether that Session owned a deleted task. Cancellation does not roll back an in-flight write.
|
|
@@ -310,14 +318,20 @@ let ScheduleService = (() => {
|
|
|
310
318
|
* binding without activating the Session or changing saved deliveries.
|
|
311
319
|
*
|
|
312
320
|
* Each supplied field replaces its stored value; an omitted field keeps it. A name or
|
|
313
|
-
* instruction change alone does not reset the committed target.
|
|
321
|
+
* instruction change alone does not reset the committed target. A Session a delegated
|
|
322
|
+
* child owns returns the non-mutating `subagent_session` result, so an edit cannot
|
|
323
|
+
* re-arm a task bound to a Session delivery can never reach, and the Web editor can
|
|
324
|
+
* explain the refusal through the ordinary result it already renders.
|
|
314
325
|
* @param request - Task binding, complete observed record, and any combination of timing, name, and instruction.
|
|
315
326
|
* @param signal - Cancellation checked after domain readiness and FIFO waits, before persistence begins.
|
|
316
|
-
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict result.
|
|
327
|
+
* @returns The committed record, unchanged record for a no-op, or a non-mutating input/lookup/conflict/refusal result.
|
|
317
328
|
* Storage and lifecycle failures reject; cancellation after a write starts does not roll it back.
|
|
318
329
|
*/
|
|
319
330
|
async update(request, signal) {
|
|
320
331
|
return this.serialize(async () => {
|
|
332
|
+
const refusal = this.reminderTargetRefusal(request.sessionId);
|
|
333
|
+
if (refusal !== undefined)
|
|
334
|
+
return refusal;
|
|
321
335
|
const tasks = (await this.getDomain()).table('tasks');
|
|
322
336
|
signal?.throwIfAborted();
|
|
323
337
|
const current = tasks.get(request.id);
|
|
@@ -356,6 +370,27 @@ let ScheduleService = (() => {
|
|
|
356
370
|
await this.initialized;
|
|
357
371
|
return this.ready;
|
|
358
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Refuse a Session no delivery can reach because a delegated child owns it.
|
|
375
|
+
*
|
|
376
|
+
* Delivery resolves the bound Session through `ctx.sessionController.resolveAgent`,
|
|
377
|
+
* which rejects the live Agent of a delegated child; a stored task for such a Session
|
|
378
|
+
* would stay permanently overdue and retry on every drive. Both operations that can
|
|
379
|
+
* arm a delivery read that same fact here instead of restating it: a delegated child
|
|
380
|
+
* is one whose {@link delegationDepthOf} is above zero, the accounting the delegation
|
|
381
|
+
* cap itself enforces, which survives a cold resume through the persisted header.
|
|
382
|
+
* @param sessionId - Session the task would be bound to.
|
|
383
|
+
* @returns The stable refusal for a delegated child's Session, or undefined when the Session is eligible.
|
|
384
|
+
*/
|
|
385
|
+
reminderTargetRefusal(sessionId) {
|
|
386
|
+
const agent = this.ctx.agents.get(sessionId);
|
|
387
|
+
if (agent === undefined || delegationDepthOf(agent) === 0)
|
|
388
|
+
return undefined;
|
|
389
|
+
return {
|
|
390
|
+
code: 'subagent_session',
|
|
391
|
+
message: 'This Session belongs to subagent routing, which never receives reminder delivery.',
|
|
392
|
+
};
|
|
393
|
+
}
|
|
359
394
|
/**
|
|
360
395
|
* Remove every active task stored for one Session, inside the queue the tools
|
|
361
396
|
* use.
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qilin-agent/schedule",
|
|
3
3
|
"description": "Host-wide durable reminders with shared management and original-Session delivery",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -34,9 +34,11 @@
|
|
|
34
34
|
"./remote": {
|
|
35
35
|
"types": "./lib/typert.remote-client.d.ts",
|
|
36
36
|
"default": "./lib/typert.remote-client.js"
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
|
+
"./locale/*.json": "./locale/*.json"
|
|
38
39
|
},
|
|
39
40
|
"files": [
|
|
41
|
+
"locale/*.json",
|
|
40
42
|
"lib/index.js",
|
|
41
43
|
"lib/types/**/*.js",
|
|
42
44
|
"lib/types/**/*.d.ts",
|
|
@@ -47,41 +49,43 @@
|
|
|
47
49
|
],
|
|
48
50
|
"license": "MIT",
|
|
49
51
|
"peerDependencies": {
|
|
50
|
-
"@qilin-agent/agent": "3.1.
|
|
51
|
-
"@qilin-agent/
|
|
52
|
-
"@qilin-agent/
|
|
53
|
-
"@qilin-agent/
|
|
54
|
-
"@qilin-agent/
|
|
55
|
-
"@qilin-agent/session-
|
|
56
|
-
"@qilin-agent/
|
|
57
|
-
"@qilin-agent/
|
|
58
|
-
"@qilin-agent/
|
|
59
|
-
"@qilin-agent/
|
|
60
|
-
"@qilin-agent/
|
|
52
|
+
"@qilin-agent/agent": "3.1.6",
|
|
53
|
+
"@qilin-agent/llm": "3.1.6",
|
|
54
|
+
"@qilin-agent/session": "3.1.6",
|
|
55
|
+
"@qilin-agent/session-projection": "3.1.6",
|
|
56
|
+
"@qilin-agent/storage-domain": "3.1.6",
|
|
57
|
+
"@qilin-agent/api-session-controller": "3.1.6",
|
|
58
|
+
"@qilin-agent/subagent": "3.1.6",
|
|
59
|
+
"@qilin-agent/tools": "3.1.6",
|
|
60
|
+
"@qilin-agent/brand": "3.1.6",
|
|
61
|
+
"@qilin-agent/session-persistence": "3.1.6",
|
|
62
|
+
"@qilin-agent/typert-protocol": "3.1.6",
|
|
63
|
+
"@qilin-agent/kylin": "~4.0.5"
|
|
61
64
|
},
|
|
62
65
|
"dependencies": {
|
|
63
66
|
"@js-temporal/polyfill": "0.5.1",
|
|
64
67
|
"zod": "^4.4.3",
|
|
65
|
-
"@qilin-agent/schemastery": "~3.18.
|
|
68
|
+
"@qilin-agent/schemastery": "~3.18.5"
|
|
66
69
|
},
|
|
67
70
|
"devDependencies": {
|
|
68
|
-
"@qilin-agent/
|
|
69
|
-
"@qilin-agent/
|
|
70
|
-
"@qilin-agent/agent-loop": "3.1.
|
|
71
|
-
"@qilin-agent/api-session-controller": "3.1.
|
|
72
|
-
"@qilin-agent/agent-loop
|
|
73
|
-
"@qilin-agent/
|
|
74
|
-
"@qilin-agent/session": "3.1.
|
|
75
|
-
"@qilin-agent/
|
|
76
|
-
"@qilin-agent/session-
|
|
77
|
-
"@qilin-agent/
|
|
78
|
-
"@qilin-agent/session
|
|
79
|
-
"@qilin-agent/storage-domain": "3.1.
|
|
80
|
-
"@qilin-agent/
|
|
81
|
-
"@qilin-agent/
|
|
82
|
-
"@qilin-agent/
|
|
83
|
-
"@qilin-agent/
|
|
84
|
-
"@qilin-agent/
|
|
85
|
-
"@qilin-agent/typert-protocol": "3.1.
|
|
71
|
+
"@qilin-agent/kylin-plugin-loader": "~1.0.6",
|
|
72
|
+
"@qilin-agent/agent": "3.1.6",
|
|
73
|
+
"@qilin-agent/agent-loop-testkit": "3.1.6",
|
|
74
|
+
"@qilin-agent/api-session-controller": "3.1.6",
|
|
75
|
+
"@qilin-agent/agent-loop": "3.1.6",
|
|
76
|
+
"@qilin-agent/brand": "3.1.6",
|
|
77
|
+
"@qilin-agent/session-persistence": "3.1.6",
|
|
78
|
+
"@qilin-agent/session-persistence-jsonl": "3.1.6",
|
|
79
|
+
"@qilin-agent/session-projection": "3.1.6",
|
|
80
|
+
"@qilin-agent/llm": "3.1.6",
|
|
81
|
+
"@qilin-agent/session": "3.1.6",
|
|
82
|
+
"@qilin-agent/storage-domain": "3.1.6",
|
|
83
|
+
"@qilin-agent/subagent": "3.1.6",
|
|
84
|
+
"@qilin-agent/storage": "3.1.6",
|
|
85
|
+
"@qilin-agent/tools": "3.1.6",
|
|
86
|
+
"@qilin-agent/system-prompt": "3.1.6",
|
|
87
|
+
"@qilin-agent/storage-json": "3.1.6",
|
|
88
|
+
"@qilin-agent/typert-protocol": "3.1.6",
|
|
89
|
+
"@qilin-agent/kylin": "~4.0.5"
|
|
86
90
|
}
|
|
87
91
|
}
|