dsh-later 1.0.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/CHANGELOG.md +51 -0
- package/LICENSE +21 -0
- package/README.en.md +213 -0
- package/README.md +213 -0
- package/cordis.patch.yml +19 -0
- package/lib/client.js +2384 -0
- package/lib/commands.js +531 -0
- package/lib/domain.js +14 -0
- package/lib/index.js +298 -0
- package/lib/owned-event-registration.js +46 -0
- package/lib/ownership-store.js +214 -0
- package/lib/presence.js +71 -0
- package/lib/projection.js +236 -0
- package/lib/runtime.js +407 -0
- package/lib/smart-window.js +260 -0
- package/lib/time-utils.js +170 -0
- package/lib/types/commands.d.ts +109 -0
- package/lib/types/domain.d.ts +109 -0
- package/lib/types/index.d.ts +36 -0
- package/lib/types/owned-event-registration.d.ts +22 -0
- package/lib/types/ownership-store.d.ts +20 -0
- package/lib/types/presence.d.ts +56 -0
- package/lib/types/projection.d.ts +115 -0
- package/lib/types/runtime.d.ts +111 -0
- package/lib/types/smart-window.d.ts +103 -0
- package/lib/types/time-utils.d.ts +48 -0
- package/lib/types/user-tools.d.ts +176 -0
- package/lib/user-tools.js +463 -0
- package/package.json +94 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 把 `OWNED_EVENT` 注册进宿主的已知会话事件类型集合(进程级、幂等)。
|
|
3
|
+
*
|
|
4
|
+
* 2026-09 起插件**不再写入**该事件(所有权改存 sidecar,见 ownership-store.ts),
|
|
5
|
+
* 本注册保留为**读兼容**:早期版本写入的历史日志(含当前 format 的日志)仍含
|
|
6
|
+
* 此事件类型,未注册时宿主读路径会以「unknown event type not marked ignorable」
|
|
7
|
+
* 拒读整份日志。
|
|
8
|
+
*
|
|
9
|
+
* 历史教训(为什么当初需要它 + 为什么现在不再写入):当前构建的
|
|
10
|
+
* `Session.append(type, data)` 不暴露 envelope 的 `ignorable` 字段,插件无法
|
|
11
|
+
* 在写入侧自保;持久化层在特定时序下会「seq 已消费但行未落盘」,在日志里留下
|
|
12
|
+
* 永久 seq 缺口,任何读方(含 v0→v3 格式迁移)都会拒读整份历史(GUI 表现为
|
|
13
|
+
* 「历史加载失败」)。唯一根治 = 不往会话日志写宿主词汇表之外的事件。
|
|
14
|
+
*
|
|
15
|
+
* 安全性:该事件是纯信息性的所有权记录,`{version, operation, id}` 自描述;
|
|
16
|
+
* dsh-schedule 的 fold 天然跳过它,本插件投影按严格解码消费,把它当作
|
|
17
|
+
* 「已知必需」不会让任何读者误解释日志其余部分。
|
|
18
|
+
*
|
|
19
|
+
* TODO(上游):待 dsh-session 暴露 append 侧的 `ignorable` 标记后,改为写入
|
|
20
|
+
* 时标记(更符合 envelope 契约),并移除本注册。
|
|
21
|
+
*/
|
|
22
|
+
export declare function registerOwnedSessionEventType(): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { UserScheduleDelivery } from './domain.js';
|
|
2
|
+
/** 单条所有权记录。 */
|
|
3
|
+
export interface OwnedEntry {
|
|
4
|
+
/** 到点注入形态(/later 为 'user',其余 'context')。 */
|
|
5
|
+
readonly delivery: UserScheduleDelivery;
|
|
6
|
+
/** 创建时刻(epoch ms,诊断用)。 */
|
|
7
|
+
readonly createdAt: number;
|
|
8
|
+
}
|
|
9
|
+
/** 读取某会话的全部所有权记录(缓存优先;返回副本语义,调用方不得变更)。 */
|
|
10
|
+
export declare function allOwnership(sessionId: string): Readonly<Record<string, OwnedEntry>>;
|
|
11
|
+
/** 某 schedule id 是否由用户工具创建。 */
|
|
12
|
+
export declare function hasOwnership(sessionId: string, id: string): boolean;
|
|
13
|
+
/** 某条所有权记录(缺失返回 undefined)。 */
|
|
14
|
+
export declare function getOwnership(sessionId: string, id: string): OwnedEntry | undefined;
|
|
15
|
+
/** 记录(新增或覆盖)一条所有权;幂等。 */
|
|
16
|
+
export declare function recordOwnership(sessionId: string, id: string, delivery: UserScheduleDelivery): void;
|
|
17
|
+
/** 撤销一条所有权;幂等(不存在时无操作)。 */
|
|
18
|
+
export declare function removeOwnership(sessionId: string, id: string): void;
|
|
19
|
+
/** 测试辅助:清空进程内缓存(不删文件)。 */
|
|
20
|
+
export declare function resetCacheForTests(): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 侧栏「定时状态」badge 的纯逻辑(宿主与客户端共享)。
|
|
3
|
+
*
|
|
4
|
+
* 数据源说明(路线 B 的关键事实):本插件的 `userSchedules` 投影是
|
|
5
|
+
* client-visible 单元,宿主在 `session.list` 基线里为**每个**会话携带
|
|
6
|
+
* projections 块(live 会话走注册表现值,冷会话走持久化投影缓存,零日志
|
|
7
|
+
* 加载);客户端把每行的块喂进 per-session 投影 store,并合入
|
|
8
|
+
* `SessionSummary.projectionValues`。因此客户端从 `sessions.list` 就能拿到
|
|
9
|
+
* 跨会话的任务概要,**无需宿主新增任何数据通道**。
|
|
10
|
+
*
|
|
11
|
+
* 本模块不触碰 DOM / React,全部函数可在 node --test 下运行。
|
|
12
|
+
* @module dsh-later/presence
|
|
13
|
+
*/
|
|
14
|
+
/** badge 状态:正常排期 / 紧急(≤5min)/ 到期未派发(瞬时,等会话空闲)。 */
|
|
15
|
+
export type PresenceBadgeState = 'scheduled' | 'urgent' | 'overdue';
|
|
16
|
+
/** 紧急窗口:下次触发在该窗口内时,badge 从 scheduled 升级为 urgent。 */
|
|
17
|
+
export declare const PRESENCE_URGENT_WINDOW_MS: number;
|
|
18
|
+
/** 参与归纳的最小任务形状(投影 wire 项 / runtime 记录的超集)。 */
|
|
19
|
+
export interface PresenceScheduleLike {
|
|
20
|
+
readonly scheduled_at?: string;
|
|
21
|
+
readonly scheduledAt?: string;
|
|
22
|
+
}
|
|
23
|
+
/** 由一组活动任务归纳的 badge 概要。 */
|
|
24
|
+
export interface PresenceSummary {
|
|
25
|
+
/** 可解析触发时刻的活动任务数量。 */
|
|
26
|
+
readonly count: number;
|
|
27
|
+
/** 最早触发时刻(epoch ms);全部不可解析时缺省。 */
|
|
28
|
+
readonly nextAt?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 归纳:取最早触发时刻 + 可解析数量。`every` 类任务在投影里携带推进后的
|
|
32
|
+
* `scheduledAt`(下次触发点),与一次性任务同构参与排序。
|
|
33
|
+
*/
|
|
34
|
+
export declare function summarizeSchedules(schedules: readonly PresenceScheduleLike[] | undefined): PresenceSummary;
|
|
35
|
+
/** 由当前时刻判定 badge 状态。 */
|
|
36
|
+
export declare function badgeStateFor(nextAt: number | undefined, now: number): PresenceBadgeState;
|
|
37
|
+
/** 相对触发时间的文案槽位(由调用方按语言准备;时间串经 formatHhmm 注入)。 */
|
|
38
|
+
export interface RelativeFireLabels {
|
|
39
|
+
/** ≤1 分钟:即将发送。 */
|
|
40
|
+
readonly imminent: string;
|
|
41
|
+
/** 1–59 分钟:{m} 分后。 */
|
|
42
|
+
readonly minutes: (m: number) => string;
|
|
43
|
+
/** 今天且 ≥1 小时:{h} 小时后。 */
|
|
44
|
+
readonly hours: (h: number) => string;
|
|
45
|
+
/** 明天:明天 {time}。 */
|
|
46
|
+
readonly tomorrow: (time: string) => string;
|
|
47
|
+
/** 已到期 / 更远日期缺省时钟面。 */
|
|
48
|
+
readonly clock: (time: string) => string;
|
|
49
|
+
/** ≥2 天:{date} {time}。 */
|
|
50
|
+
readonly date: (date: string, time: string) => string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 下次触发的相对时间标签。已到期(≤0)返回绝对时钟面(overdue 态文案由
|
|
54
|
+
* 调用方另行处理),≤1min 返回「即将发送」,其余按 分/小时/明天/日期 分档。
|
|
55
|
+
*/
|
|
56
|
+
export declare function relativeFireLabel(nextAt: number, now: number, labels: RelativeFireLabels, formatHhmm: (epoch: number) => string, formatDate: (epoch: number) => string): string;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `userSchedules` 会话投影:宿主侧维护的「用户创建的、当前活动的定时提醒」,
|
|
3
|
+
* 通过 `session/projection` 帧实时推给客户端(GUI 用 `useProjection` 读取)。
|
|
4
|
+
*
|
|
5
|
+
* fold 输入两路事件:
|
|
6
|
+
* - `schedule/change`:dsh-schedule 的严格 v1 事件(我们写入时与其完全兼容),
|
|
7
|
+
* 用其导出的 `decodeScheduleChange` 解码;
|
|
8
|
+
* - `session-scheduler/user-schedule`:本插件自有的所有权记录(哪种来源)。
|
|
9
|
+
*
|
|
10
|
+
* fork 隔离:`session/end-seed` 标记派生会话的耐久边界。投影在遇到该事件时
|
|
11
|
+
* 重置自身状态(清空 owned/active),因此子会话不继承父会话的提醒(AC-07)。
|
|
12
|
+
*
|
|
13
|
+
* 注意 `apply` 为增量 fold:无关事件必须返回同一状态引用,否则会误触发推送。
|
|
14
|
+
* @module dsh-later/projection
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
18
|
+
import type { ScheduleRecord } from '@deepseek-ai/dsh-schedule';
|
|
19
|
+
import type { UserScheduleProjectionValue } from './domain.js';
|
|
20
|
+
/** 投影 wire 值 schema(wire.viewSchema:离开宿主前校验客户端载荷)。 */
|
|
21
|
+
export declare const userSchedulesSchema: z.ZodObject<{
|
|
22
|
+
schedules: z.ZodArray<z.ZodObject<{
|
|
23
|
+
id: z.ZodString;
|
|
24
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"after">, z.ZodLiteral<"at">, z.ZodLiteral<"every">]>;
|
|
25
|
+
prompt: z.ZodString;
|
|
26
|
+
after_seconds: z.ZodOptional<z.ZodNumber>;
|
|
27
|
+
every_seconds: z.ZodOptional<z.ZodNumber>;
|
|
28
|
+
scheduled_at: z.ZodString;
|
|
29
|
+
created_at: z.ZodOptional<z.ZodString>;
|
|
30
|
+
delivery_mode: z.ZodLiteral<"session-local">;
|
|
31
|
+
}, z.core.$strict>>;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
export declare const userSchedulesStateSchema: z.ZodObject<{
|
|
34
|
+
sessionId: z.ZodString;
|
|
35
|
+
owned: z.ZodArray<z.ZodString>;
|
|
36
|
+
active: z.ZodArray<z.ZodObject<{
|
|
37
|
+
id: z.ZodString;
|
|
38
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"after">, z.ZodLiteral<"at">, z.ZodLiteral<"every">]>;
|
|
39
|
+
prompt: z.ZodString;
|
|
40
|
+
afterSeconds: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
everySeconds: z.ZodOptional<z.ZodNumber>;
|
|
42
|
+
scheduledAt: z.ZodString;
|
|
43
|
+
createdAt: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
}, z.core.$loose>>;
|
|
45
|
+
seedSeq: z.ZodNumber;
|
|
46
|
+
}, z.core.$strip>;
|
|
47
|
+
/** 活动存储记录:dsh-schedule 记录 + 创建时刻(来自 create 事件的 time)。 */
|
|
48
|
+
export type StoredScheduleRecord = ScheduleRecord & {
|
|
49
|
+
readonly createdAt?: number;
|
|
50
|
+
};
|
|
51
|
+
/** 投影内部状态(plain JSON:owned/active 用数组承载)。 */
|
|
52
|
+
export interface UserScheduleProjectionState {
|
|
53
|
+
/** 会话 id(init 由 header 注入)。 */
|
|
54
|
+
readonly sessionId: string;
|
|
55
|
+
/** 用户工具创建的 schedule id 集合。 */
|
|
56
|
+
readonly owned: readonly string[];
|
|
57
|
+
/** 当前活动记录(按 schedule/change 严格 fold)。 */
|
|
58
|
+
readonly active: readonly StoredScheduleRecord[];
|
|
59
|
+
/** 已见 `session/end-seed` 的 seq;更早的继承前缀一律忽略。 */
|
|
60
|
+
readonly seedSeq: number;
|
|
61
|
+
}
|
|
62
|
+
/** 初始状态:按会话 id 从所有权 sidecar 装载(进程重启后恢复 GUI 归属)。 */
|
|
63
|
+
export declare function initUserScheduleProjection(header?: {
|
|
64
|
+
readonly id?: string;
|
|
65
|
+
}): UserScheduleProjectionState;
|
|
66
|
+
/**
|
|
67
|
+
* 增量 fold。返回同一引用当事件无关;返回新状态当 owned/active 发生变化。
|
|
68
|
+
*/
|
|
69
|
+
export declare function applyUserScheduleProjection(state: UserScheduleProjectionState, event: SessionEvent): UserScheduleProjectionState;
|
|
70
|
+
/** 投影 view:只暴露用户创建的、当前活动的记录。 */
|
|
71
|
+
export declare function viewUserScheduleProjection(state: UserScheduleProjectionState): UserScheduleProjectionValue;
|
|
72
|
+
/**
|
|
73
|
+
* 投影单元声明(传给 sessionProjections.register)。
|
|
74
|
+
*
|
|
75
|
+
* 形状必须匹配 `ProjectionDefinition`:
|
|
76
|
+
* - `stateSchema`(不是 schema):宿主持久化缓存恢复前校验内部状态;
|
|
77
|
+
* - `wire: { viewSchema, view }`(不是顶层 view):**只有带 wire 的单元才是
|
|
78
|
+
* client-visible 的**——`snapshot()`/变更帧都会跳过无 wire 的单元,
|
|
79
|
+
* 客户端 `useProjection(key)` 将永远读到 undefined。
|
|
80
|
+
*/
|
|
81
|
+
export declare const userSchedulesProjectionUnit: {
|
|
82
|
+
readonly key: "userSchedules";
|
|
83
|
+
readonly stateSchema: z.ZodObject<{
|
|
84
|
+
sessionId: z.ZodString;
|
|
85
|
+
owned: z.ZodArray<z.ZodString>;
|
|
86
|
+
active: z.ZodArray<z.ZodObject<{
|
|
87
|
+
id: z.ZodString;
|
|
88
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"after">, z.ZodLiteral<"at">, z.ZodLiteral<"every">]>;
|
|
89
|
+
prompt: z.ZodString;
|
|
90
|
+
afterSeconds: z.ZodOptional<z.ZodNumber>;
|
|
91
|
+
everySeconds: z.ZodOptional<z.ZodNumber>;
|
|
92
|
+
scheduledAt: z.ZodString;
|
|
93
|
+
createdAt: z.ZodOptional<z.ZodNumber>;
|
|
94
|
+
}, z.core.$loose>>;
|
|
95
|
+
seedSeq: z.ZodNumber;
|
|
96
|
+
}, z.core.$strip>;
|
|
97
|
+
readonly init: typeof initUserScheduleProjection;
|
|
98
|
+
readonly apply: typeof applyUserScheduleProjection;
|
|
99
|
+
readonly wire: {
|
|
100
|
+
readonly viewSchema: z.ZodObject<{
|
|
101
|
+
schedules: z.ZodArray<z.ZodObject<{
|
|
102
|
+
id: z.ZodString;
|
|
103
|
+
kind: z.ZodUnion<readonly [z.ZodLiteral<"after">, z.ZodLiteral<"at">, z.ZodLiteral<"every">]>;
|
|
104
|
+
prompt: z.ZodString;
|
|
105
|
+
after_seconds: z.ZodOptional<z.ZodNumber>;
|
|
106
|
+
every_seconds: z.ZodOptional<z.ZodNumber>;
|
|
107
|
+
scheduled_at: z.ZodString;
|
|
108
|
+
created_at: z.ZodOptional<z.ZodString>;
|
|
109
|
+
delivery_mode: z.ZodLiteral<"session-local">;
|
|
110
|
+
}, z.core.$strict>>;
|
|
111
|
+
}, z.core.$strict>;
|
|
112
|
+
readonly view: typeof viewUserScheduleProjection;
|
|
113
|
+
};
|
|
114
|
+
readonly stateVersion: 3;
|
|
115
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户提醒的独立调度器(per root agent)。
|
|
3
|
+
*
|
|
4
|
+
* 为什么需要它:dsh-schedule 的 runtime 只在三类时机重驱——agent 创建、**其
|
|
5
|
+
* 自身工具**的持久化变更、agent 转 idle。用户经本插件命令/工具创建的提醒不会
|
|
6
|
+
* 触发这三类,导致 timer 不武装、不到期触发(GUI 显示任务但永远不 fire)。
|
|
7
|
+
*
|
|
8
|
+
* 本调度器只处理**用户创建**的提醒,复用 dsh-schedule 导出的领域函数
|
|
9
|
+
* (fold / resolveEveryOccurrence / render*Framing)和 `agent.followup`。
|
|
10
|
+
* 防重复:两套调度器(本插件 + dsh-schedule)都通过**同一份持久化日志**做
|
|
11
|
+
* 「fold → append dispatch」的原子判断(同一 JS 线程内同步完成),先到者写入
|
|
12
|
+
* dispatch 事件后,后者 fold 即见已被派发 → 跳过,不会双触发。
|
|
13
|
+
*
|
|
14
|
+
* 触发点:用户 create/delete 成功后 requestDrive;agent 转 idle 时也
|
|
15
|
+
* requestDrive(自愈);agent 创建时启动。
|
|
16
|
+
* @module dsh-later/runtime
|
|
17
|
+
*/
|
|
18
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
19
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
20
|
+
import type { ScheduleRecord, OneShotScheduleRecord, EveryScheduleRecord } from '@deepseek-ai/dsh-schedule';
|
|
21
|
+
import type { UserScheduleDelivery } from './domain.js';
|
|
22
|
+
/** 一次「用户提醒决策」:一批同形态到期一次性、或一批到期固定间隔、或下一次等待目标。
|
|
23
|
+
*
|
|
24
|
+
* P1-5:one-shot 从单条改为**同投递形态的批次**——网页关闭期间积压的多条
|
|
25
|
+
* 到期提醒合并为一条注入消息,而不是逐条刷屏。批次内投递形态必然一致
|
|
26
|
+
* (`/later` 与 `/schedule` 不同组,各组按时间先后分轮派发)。
|
|
27
|
+
*/
|
|
28
|
+
type UserDecision = {
|
|
29
|
+
kind: 'one-shot';
|
|
30
|
+
delivery: UserScheduleDelivery;
|
|
31
|
+
records: readonly OneShotScheduleRecord[];
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'every';
|
|
34
|
+
acceptedAt: string;
|
|
35
|
+
reminders: readonly {
|
|
36
|
+
record: EveryScheduleRecord;
|
|
37
|
+
occurrenceAt: string;
|
|
38
|
+
}[];
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'wait';
|
|
41
|
+
target?: number;
|
|
42
|
+
};
|
|
43
|
+
export declare function dueUserDecision(active: readonly ScheduleRecord[], now: number, delivery?: ReadonlyMap<string, UserScheduleDelivery>): UserDecision;
|
|
44
|
+
/** 每个 agent 的独立调度器。 */
|
|
45
|
+
export declare class UserScheduleRuntime {
|
|
46
|
+
private readonly ctx;
|
|
47
|
+
private readonly agent;
|
|
48
|
+
private readonly stop;
|
|
49
|
+
private resolveStop;
|
|
50
|
+
private timer;
|
|
51
|
+
private run;
|
|
52
|
+
private requested;
|
|
53
|
+
private stopping;
|
|
54
|
+
/** 连续 run 级失败次数(P0-3:用于指数退避,成功一次即清零)。 */
|
|
55
|
+
private failures;
|
|
56
|
+
private idleWait;
|
|
57
|
+
private disposal;
|
|
58
|
+
constructor(ctx: Context, agent: Agent);
|
|
59
|
+
/** 是否仍为活动 root agent。 */
|
|
60
|
+
private isLive;
|
|
61
|
+
/** 发起一次重算(合并多个触发为一次)。 */
|
|
62
|
+
requestDrive(): void;
|
|
63
|
+
/** 清空已武装的 timer。 */
|
|
64
|
+
private clearTimer;
|
|
65
|
+
/** 武装一次到下次目标的 timer。 */
|
|
66
|
+
private arm;
|
|
67
|
+
/** 串行 drain 合并的触发。 */
|
|
68
|
+
private runRequested;
|
|
69
|
+
/** 等待一次 public 的 idle 边界(供 agent 忙碌时重试)。 */
|
|
70
|
+
private waitForIdle;
|
|
71
|
+
/** 停止调度器、取消 timer、等待在途派发收敛。 */
|
|
72
|
+
dispose(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* 用户主动插话(QueueDock「插话发送」语义):把指定 id 的提醒内容**立即**推给 agent。
|
|
75
|
+
* - 仅 one-shot(at / after)支持;every 类型因 batch framing 需要更多 plumbing,留待后续
|
|
76
|
+
* - **不要求已到点**:与 QueueDock 一致,排队中的内容随时可被主动插话提前送达;
|
|
77
|
+
* 成功即出列(写 dispatch),不会到点再 fire 一次
|
|
78
|
+
* - 与 fold/dispatch 共享「单一真相」:steer 成功后立即写 `schedule/change: dispatch`,
|
|
79
|
+
* 否则后续 fold 路径会再 fire 一次(双触发)
|
|
80
|
+
*
|
|
81
|
+
* 为什么不用 `runMaintenance`:插话按钮只在 overdue 时出现,而 overdue 恰恰发生在
|
|
82
|
+
* agent 正在跑(auto-driver 只能 waitForIdle)——`runMaintenance` 在 agent 有活跃工作
|
|
83
|
+
* 时直接 throw(`agent "..." already has active work`),会让插话在唯一可见的场景里
|
|
84
|
+
* 必然失败(曾以 `internal_error: 插话执行失败` 落日志)。`agent.steer` 是为「in-flight
|
|
85
|
+
* 也要在下一个 step boundary 立即消费」设计的原语:空闲则开 turn、忙碌则排到边界,
|
|
86
|
+
* 不需要空闲。dispatch 事件在同一同步块内 append,与 auto-driver 的 fold 无并发窗口
|
|
87
|
+
* (JS 单线程;两者要么整块先执行要么整块后执行,后执行者 fold 即见 dispatch 而跳过)。
|
|
88
|
+
*/
|
|
89
|
+
steerById(id: string): Promise<{
|
|
90
|
+
ok: true;
|
|
91
|
+
id: string;
|
|
92
|
+
steered: true;
|
|
93
|
+
} | {
|
|
94
|
+
ok: false;
|
|
95
|
+
code: string;
|
|
96
|
+
message: string;
|
|
97
|
+
}>;
|
|
98
|
+
/** 执行一次用户提醒决策与派发。 */
|
|
99
|
+
private driveOnce;
|
|
100
|
+
/**
|
|
101
|
+
* 构造注入的消息,按投递形态分流:
|
|
102
|
+
* - `user`(`/later` 显式请求的延迟发送):原样内容 + `source.kind='user'`,
|
|
103
|
+
* 让 GUI 呈现为「我」发出的普通气泡(产品取舍:用户明确要求以本人身份)。
|
|
104
|
+
* 跳过 framing 防护 —— 这是「代发」语义,不是注入。
|
|
105
|
+
* - `context`(默认):复用 dsh-schedule 的注入防护 framing + notice 表单,
|
|
106
|
+
* 保持「上下文注入」的可信审计线;多条一次性到期合并为批次 framing(P1-5),
|
|
107
|
+
* 形状与 dsh-schedule 的固定间隔批次一致。
|
|
108
|
+
*/
|
|
109
|
+
private buildMessage;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 智能时段计算(纯函数,host 与 client 共享)。
|
|
3
|
+
*
|
|
4
|
+
* 默认时段(v1 硬编码,可经 cordis config 覆盖):
|
|
5
|
+
* 工作时间 09:00–18:00
|
|
6
|
+
* 午休时间 12:00–14:00
|
|
7
|
+
* 晚间时间 18:00–22:00
|
|
8
|
+
* 夜间静默 22:00–次日 09:00(不发送)
|
|
9
|
+
*
|
|
10
|
+
* 计算在**用户显式选定的 IANA 时区**内进行(不自动推断,确定性优先)。
|
|
11
|
+
* 墙钟→epoch 的解析采用 dsh-schedule `resolveLocalInstant` 同款偏移校正法,
|
|
12
|
+
* 避免依赖进程时区。
|
|
13
|
+
* @module dsh-later/smart-window
|
|
14
|
+
*/
|
|
15
|
+
/** 智能时段配置(HH:mm 格式,可配置)。 */
|
|
16
|
+
export interface SmartWindowConfig {
|
|
17
|
+
/** 工作时间开始。 */
|
|
18
|
+
readonly workStart: string;
|
|
19
|
+
/** 工作时间结束。 */
|
|
20
|
+
readonly workEnd: string;
|
|
21
|
+
/** 午休开始。 */
|
|
22
|
+
readonly lunchStart: string;
|
|
23
|
+
/** 午休结束。 */
|
|
24
|
+
readonly lunchEnd: string;
|
|
25
|
+
/** 晚间结束(夜间静默起点)。 */
|
|
26
|
+
readonly eveningEnd: string;
|
|
27
|
+
}
|
|
28
|
+
/** 默认时段。 */
|
|
29
|
+
export declare const DEFAULT_SMART_WINDOW: SmartWindowConfig;
|
|
30
|
+
/** 校验一个 HH:mm 字符串。 */
|
|
31
|
+
export declare function isValidHhmm(value: unknown): value is string;
|
|
32
|
+
/**
|
|
33
|
+
* 清洗用户/配置层提供的时段字段:非法或缺省的字段逐项回落默认值
|
|
34
|
+
* (host schema 与 client 设置面共用;保证下游 `nextSmartTarget` 永不因脏输入抛错)。
|
|
35
|
+
*/
|
|
36
|
+
export declare function sanitizeSmartWindowConfig(raw: Partial<Record<keyof SmartWindowConfig, unknown>> | undefined | null): SmartWindowConfig;
|
|
37
|
+
/** 两次提醒之间至少等待的毫秒数(智能模式下)。 */
|
|
38
|
+
export declare const SMART_MIN_DELAY_MS: number;
|
|
39
|
+
/** 一小时/一天的毫秒数。 */
|
|
40
|
+
export declare const MINUTE_MS: number;
|
|
41
|
+
export declare const HOUR_MS: number;
|
|
42
|
+
export declare const DAY_MS: number;
|
|
43
|
+
/** 当日第几分钟(0–1439)。 */
|
|
44
|
+
export type DayMinutes = number;
|
|
45
|
+
/** 本地日历字段。 */
|
|
46
|
+
export interface LocalFields {
|
|
47
|
+
readonly year: number;
|
|
48
|
+
readonly month: number;
|
|
49
|
+
readonly day: number;
|
|
50
|
+
readonly hour: number;
|
|
51
|
+
readonly minute: number;
|
|
52
|
+
readonly second: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 把 "HH:mm" 解析为当日第几分钟;非法返回 undefined。
|
|
56
|
+
*/
|
|
57
|
+
export declare function hhmmToMinutes(value: string): DayMinutes | undefined;
|
|
58
|
+
/** 把当日第几分钟格式化为 "HH:mm"。 */
|
|
59
|
+
export declare function minutesToHhmm(minutes: DayMinutes): string;
|
|
60
|
+
/**
|
|
61
|
+
* 可配置时段是否有效:所有边界均为合法 HH:mm 且满足
|
|
62
|
+
* workStart < lunchStart < lunchEnd < workEnd < eveningEnd。
|
|
63
|
+
*/
|
|
64
|
+
export declare function isValidWindow(window: SmartWindowConfig): boolean;
|
|
65
|
+
/** 取整到整分钟(秒、毫秒清零)。 */
|
|
66
|
+
export declare function floorToMinute(epoch: number): number;
|
|
67
|
+
/** 把 epoch 投影到指定时区的本地日历字段。 */
|
|
68
|
+
export declare function localFieldsOf(epoch: number, timeZone: string): LocalFields;
|
|
69
|
+
/**
|
|
70
|
+
* 解析一个本地墙钟时刻(hour/min 表示,sec=00)在指定时区内对应的 epoch。
|
|
71
|
+
* 采用「偏移校正」法:把墙钟当 UTC 构造候选,再用采样偏移反推真实 epoch,
|
|
72
|
+
* 并验证映射回原墙钟字段;DST 重叠取最早候选,缺口会导致无候选。
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveWallClock(epochOnDay: number, timeZone: string, hour: number, minute: number, second?: number): number | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* 计算下一个智能时段的本地墙钟目标。
|
|
77
|
+
*
|
|
78
|
+
* 规则:
|
|
79
|
+
* - 若当前在午休时段(lunchStart ≤ now < lunchEnd)→ 目标为 now + 2 分钟;
|
|
80
|
+
* - 否则候选为下一个 工作开始 / 午休结束 / 晚间开始(均 > now + 2 分钟),取最早者;
|
|
81
|
+
* - 夜间静默(≥ eveningEnd 或 < workStart)自然被「下一个工作开始」覆盖。
|
|
82
|
+
*
|
|
83
|
+
* @param now - 当前墙钟 epoch 毫秒。
|
|
84
|
+
* @param timeZone - 用户显式选定的 IANA 时区。
|
|
85
|
+
* @param window - 时段配置(默认 {@link DEFAULT_SMART_WINDOW})。
|
|
86
|
+
* @returns 目标 epoch 毫秒(严格位于未来,且至少 SMART_MIN_DELAY_MS 之后)。
|
|
87
|
+
*/
|
|
88
|
+
export declare function nextSmartTarget(now: number, timeZone: string, window?: SmartWindowConfig): number;
|
|
89
|
+
/**
|
|
90
|
+
* 把本地墙钟字符串(date YYYY-MM-DD、time HH:mm[:ss])在指定时区解析为 epoch。
|
|
91
|
+
* 用于自定义时间的预览与合法性校验。解析失败返回 undefined(如 DST 缺口)。
|
|
92
|
+
*/
|
|
93
|
+
export declare function epochFromLocal(date: string, time: string, timeZone: string): number | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* 智能模式的一站式目标构造:返回可直接作为 `at` 对象使用的本地日历字段。
|
|
96
|
+
* @returns null 当配置非法或无法解析时。
|
|
97
|
+
*/
|
|
98
|
+
export declare function nextSmartAt(now: number, timeZone: string, window?: SmartWindowConfig): {
|
|
99
|
+
date: string;
|
|
100
|
+
time: string;
|
|
101
|
+
time_zone: string;
|
|
102
|
+
epoch: number;
|
|
103
|
+
} | null;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 时间格式化与通用工具(纯函数,host 与 client 共享)。
|
|
3
|
+
* 文案遵循 docs/ui/08-microcopy.md 的微文案规范。
|
|
4
|
+
* @module dsh-later/time-utils
|
|
5
|
+
*/
|
|
6
|
+
/** 校验一个字符串是否为合法 IANA 时区(或 UTC)。 */
|
|
7
|
+
export declare function isValidTimeZone(value: string): boolean;
|
|
8
|
+
/** 浏览器默认时区(客户端);host 侧无合理默认则退回 UTC。 */
|
|
9
|
+
export declare function detectTimeZone(): string;
|
|
10
|
+
/** 常见时区候选(面板下拉用)。 */
|
|
11
|
+
export declare const COMMON_TIME_ZONES: readonly string[];
|
|
12
|
+
/** 文案语言 id(zh 中文;en 英文;其余回退中文)。 */
|
|
13
|
+
export type TextLocale = 'zh' | 'en';
|
|
14
|
+
/**
|
|
15
|
+
* 相对时间文案:zh "约 X 分钟后";en "in ~X minutes" 等。
|
|
16
|
+
* @param epoch - 目标 epoch 毫秒。
|
|
17
|
+
* @param now - 当前 epoch 毫秒(默认 Date.now())。
|
|
18
|
+
* @param locale - 文案语言(默认 zh,host 侧无浏览器语境保持中文)。
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatRelative(epoch: number, now?: number, locale?: TextLocale): string;
|
|
21
|
+
/** 毫秒常量(避免依赖 smart-window 再复制)。 */
|
|
22
|
+
export declare const MINUTE_MS: number;
|
|
23
|
+
export declare const HOUR_MS: number;
|
|
24
|
+
export declare const DAY_MS: number;
|
|
25
|
+
/**
|
|
26
|
+
* 完整时间文案:zh "{M}月{d}日 {周X} HH:mm"、en "Wed, Aug 26, 14:45"(按指定时区)。
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatAbsolute(epoch: number, timeZone: string, locale?: TextLocale): string;
|
|
29
|
+
/** 仅时间部分 "HH:mm"(按指定时区)。 */
|
|
30
|
+
export declare function formatHhmm(epoch: number, timeZone: string): string;
|
|
31
|
+
/** 周期几第几天(与 formatAbsolute 里的 wkday 词对齐)。 */
|
|
32
|
+
export declare function weekdayLabel(epoch: number, timeZone: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* 倒计时 "HH:MM:SS"(或剩余不足 1 小时时 "MM:SS")。
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatCountdown(epoch: number, now?: number): string;
|
|
37
|
+
/** 未来距离(毫秒);用于紧急度判断。 */
|
|
38
|
+
export declare function remainingMs(epoch: number, now?: number): number;
|
|
39
|
+
/**
|
|
40
|
+
* 构造 `at` 对象:{date, time, time_zone}。
|
|
41
|
+
* @param epoch - 目标 epoch 毫秒。
|
|
42
|
+
* @param timeZone - IANA 时区。
|
|
43
|
+
*/
|
|
44
|
+
export declare function atObjectOf(epoch: number, timeZone: string): {
|
|
45
|
+
date: string;
|
|
46
|
+
time: string;
|
|
47
|
+
time_zone: string;
|
|
48
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 用户工具核心实现:`user_schedule_create` / `user_schedule_list` /
|
|
3
|
+
* `user_schedule_delete`。
|
|
4
|
+
*
|
|
5
|
+
* 复用 dsh-schedule 导出的领域函数(fold / allocate / 各 create 函数 /
|
|
6
|
+
* scheduleView),写入**完全兼容**的 `schedule/change` 事件(不携带 `source`
|
|
7
|
+
* 字段,避免破坏 dsh-schedule 严格解码)。
|
|
8
|
+
*
|
|
9
|
+
* 用户来源(所有权 + 投递形态)记录在**插件自己的 sidecar 文件**里
|
|
10
|
+
* (ownership-store.ts),**不再写入会话日志**——2026-09 根治:伴生事件
|
|
11
|
+
* `session-scheduler/user-schedule` 曾因宿主持久化静默丢行而留下永久 seq
|
|
12
|
+
* 缺口,让整份历史被拒读。日志里若仍残留旧的伴生事件(历史日志),fold
|
|
13
|
+
* 会继续读取(读兼容),但本模块不再产生它们。
|
|
14
|
+
*
|
|
15
|
+
* 所有读改写操作按 agent 串行化(同 dsh-schedule 的 agent-scoped 队列),
|
|
16
|
+
* 保证 id 分配与 fold 不会并发竞争。
|
|
17
|
+
* @module dsh-later/user-tools
|
|
18
|
+
*/
|
|
19
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
20
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
21
|
+
import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
|
|
22
|
+
import { foldScheduleEvents } from '@deepseek-ai/dsh-schedule';
|
|
23
|
+
import type { ScheduleRecord, ScheduleView } from '@deepseek-ai/dsh-schedule';
|
|
24
|
+
import type { UserScheduleDelivery } from './domain.js';
|
|
25
|
+
/** 单 session 用户任务上限(PRD:防滥用)。 */
|
|
26
|
+
export declare const DEFAULT_MAX_SCHEDULES = 100;
|
|
27
|
+
/**
|
|
28
|
+
* 经过 trim 后允许的默认最大提示字符数(P0:注入防护的保守下限)。
|
|
29
|
+
*
|
|
30
|
+
* 当 settings 中 `allowLongPrompts=false` 时此值始终生效;为 `true` 时
|
|
31
|
+
* 由 `maxPromptChars` 字段接管实际字符上限。用户必须显式 opt-in 才解除
|
|
32
|
+
* 该硬上限——保持默认安全的姿态。
|
|
33
|
+
*/
|
|
34
|
+
export declare const DEFAULT_MAX_PROMPT_CHARS = 1000;
|
|
35
|
+
/** 用户工具的提示字符上限策略(来自插件 settings)。 */
|
|
36
|
+
export interface PromptLimits {
|
|
37
|
+
/** 是否解除 `DEFAULT_MAX_PROMPT_CHARS` 硬上限;未开启时 maxChars 始终等于默认值。 */
|
|
38
|
+
readonly allowLong: boolean;
|
|
39
|
+
/** 当前允许的最大字符数(已根据 allowLong 解析过)。 */
|
|
40
|
+
readonly maxChars: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 从 settings 解析出实际生效的 PromptLimits。
|
|
44
|
+
* 容错非法值(NaN / 负数 / 非数)回落 DEFAULT_MAX_PROMPT_CHARS。
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolvePromptLimits(settings: {
|
|
47
|
+
readonly allowLongPrompts?: boolean;
|
|
48
|
+
readonly maxPromptChars?: number;
|
|
49
|
+
} | undefined): PromptLimits;
|
|
50
|
+
/** 单条提示的字符校验(纯函数)。返回 trim 后的字符串或闭包错误。 */
|
|
51
|
+
export declare function validatePrompt(raw: unknown, limits: PromptLimits): {
|
|
52
|
+
ok: true;
|
|
53
|
+
value: string;
|
|
54
|
+
} | UserScheduleError;
|
|
55
|
+
/** 用户工具稳定的闭包错误集合(在 dsh-schedule 闭包之上追加本插件专用码)。 */
|
|
56
|
+
export type UserScheduleErrorCode = 'invalid_prompt' | 'invalid_selector' | 'invalid_time_zone' | 'not_future' | 'time_out_of_range' | 'frequency_too_high' | 'invalid_rule' | 'schedule_not_found' | 'already_overdue' | 'quota_exceeded' | 'persistence_uncertain' | 'internal_error';
|
|
57
|
+
/** 封闭错误值。 */
|
|
58
|
+
export interface UserScheduleError {
|
|
59
|
+
readonly ok: false;
|
|
60
|
+
readonly code: UserScheduleErrorCode;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
}
|
|
63
|
+
/** 成功值。 */
|
|
64
|
+
export type UserScheduleResult<TSuccess> = TSuccess | UserScheduleError;
|
|
65
|
+
/** `user_schedule_create` 成功响应。 */
|
|
66
|
+
export type UserScheduleCreateResult = UserScheduleResult<ScheduleRecordView & {
|
|
67
|
+
readonly ok: true;
|
|
68
|
+
}>;
|
|
69
|
+
/** `user_schedule_list` 成功响应。 */
|
|
70
|
+
export type UserScheduleListResult = UserScheduleResult<{
|
|
71
|
+
readonly ok: true;
|
|
72
|
+
readonly schedules: readonly ScheduleRecordView[];
|
|
73
|
+
}>;
|
|
74
|
+
/** `user_schedule_delete` 成功响应。 */
|
|
75
|
+
export type UserScheduleDeleteResult = UserScheduleResult<{
|
|
76
|
+
readonly ok: true;
|
|
77
|
+
readonly id: string;
|
|
78
|
+
readonly deleted: true;
|
|
79
|
+
} | {
|
|
80
|
+
readonly ok: true;
|
|
81
|
+
readonly id: string;
|
|
82
|
+
readonly deleted: false;
|
|
83
|
+
readonly code: 'schedule_not_found';
|
|
84
|
+
}>;
|
|
85
|
+
/** `user_schedule_create` 的规范化输入。 */
|
|
86
|
+
export interface UserScheduleCreateInput {
|
|
87
|
+
readonly prompt: string;
|
|
88
|
+
readonly time_zone: string;
|
|
89
|
+
readonly after_seconds?: number;
|
|
90
|
+
readonly at?: string | {
|
|
91
|
+
readonly date: string;
|
|
92
|
+
readonly time: string;
|
|
93
|
+
readonly time_zone: string;
|
|
94
|
+
};
|
|
95
|
+
readonly every_seconds?: number;
|
|
96
|
+
}
|
|
97
|
+
/** 校验 `user_schedule_create` 参数(纯函数,含 TRIM 非空、长度、三选一)。
|
|
98
|
+
*
|
|
99
|
+
* `limits` 可选:未传时回落到 `DEFAULT_MAX_PROMPT_CHARS`(保持向后兼容);
|
|
100
|
+
* 命令与工具的注册路径会按当前 settings 传入实际 limits,校验消息会反映
|
|
101
|
+
* 当前生效的字符上限(与模型可见的 tool description 同步)。
|
|
102
|
+
*/
|
|
103
|
+
export declare function validateCreateInput(input: unknown, limits?: PromptLimits): {
|
|
104
|
+
ok: true;
|
|
105
|
+
value: UserScheduleCreateInput;
|
|
106
|
+
} | UserScheduleError;
|
|
107
|
+
/** 校验 IANA 时区(与 dsh-schedule canonicalize 同源,容错)。 */
|
|
108
|
+
export declare function isValidIanaZone(value: string): boolean;
|
|
109
|
+
/** 从会话日志导出「用户创建过的 schedule id 集合」(历史遗留读兼容)。 */
|
|
110
|
+
export declare function foldOwnedIds(events: readonly SessionEvent[]): Set<string>;
|
|
111
|
+
/**
|
|
112
|
+
* 从会话日志导出「schedule id → 到点注入形态」映射(默认 `context`)。
|
|
113
|
+
* 供 runtime 在 dispatch 时按 `/later` 与 `/schedule` 分别注入。
|
|
114
|
+
*/
|
|
115
|
+
export declare function foldOwnedDelivery(events: readonly SessionEvent[]): ReadonlyMap<string, UserScheduleDelivery>;
|
|
116
|
+
/**
|
|
117
|
+
* 会话级 fold 缓存(P1-6):事件日志只增不改(事件溯源),
|
|
118
|
+
* 按「数组身份 + 长度」判定命中——append 原地 push 使长度变化即失效;
|
|
119
|
+
* 整体换数组则身份不同也失效。两种实现风格下都安全。
|
|
120
|
+
*
|
|
121
|
+
* 消除热路径(每次 drive / 每次工具调用)对全量日志的重复 O(n) 扫描。
|
|
122
|
+
*/
|
|
123
|
+
export interface UserFoldState {
|
|
124
|
+
readonly folded: ReturnType<typeof foldScheduleEvents>;
|
|
125
|
+
readonly owned: ReadonlySet<string>;
|
|
126
|
+
readonly delivery: ReadonlyMap<string, UserScheduleDelivery>;
|
|
127
|
+
}
|
|
128
|
+
/** fold 当前会话的完整用户调度状态(带缓存;调用方不得变更返回值)。
|
|
129
|
+
*
|
|
130
|
+
* 跨代兼容:0.1.1 暴露 `session.events` + `header.seedLength`;0.1.2 改名
|
|
131
|
+
* 为 `session.ownEvents()` + `session.inheritedEventCount`。通过鸭子类型
|
|
132
|
+
* (`(session as { ownEvents?; events? })`)双轨探测,不引入 `any`。
|
|
133
|
+
*/
|
|
134
|
+
export declare function foldUserState(session: Session): UserFoldState;
|
|
135
|
+
/** 稳定内部错误(不透出异常细节)。 */
|
|
136
|
+
export declare function internalError(): UserScheduleError;
|
|
137
|
+
/** 稳定持久化不确定错误。 */
|
|
138
|
+
export declare function persistenceError(): UserScheduleError;
|
|
139
|
+
/** 把 dsh-schedule 的 ScheduleInputError 翻译为闭包错误值。 */
|
|
140
|
+
export declare function toInputError(error: unknown): UserScheduleError;
|
|
141
|
+
/** 记录视图的 snake_case 序列化。 */
|
|
142
|
+
export type ScheduleRecordView = {
|
|
143
|
+
readonly id: string;
|
|
144
|
+
readonly kind: ScheduleRecord['kind'];
|
|
145
|
+
readonly prompt: string;
|
|
146
|
+
readonly after_seconds?: number;
|
|
147
|
+
readonly every_seconds?: number;
|
|
148
|
+
readonly scheduled_at: string;
|
|
149
|
+
readonly state: 'scheduled' | 'overdue';
|
|
150
|
+
readonly delivery_mode: 'session-local';
|
|
151
|
+
readonly source: 'user-tool';
|
|
152
|
+
};
|
|
153
|
+
/** 把 dsh-schedule 的 view 序列化为 snake_case 记录。 */
|
|
154
|
+
export declare function serializeScheduleView(view: ScheduleView): ScheduleRecordView;
|
|
155
|
+
/** 在当前 agent 的事务尾之后运行操作。 */
|
|
156
|
+
export declare function runUserScheduleTransaction<T>(agent: Agent, operation: () => Promise<T>): Promise<T>;
|
|
157
|
+
/**
|
|
158
|
+
* `user_schedule_create` 的可信通道选项。
|
|
159
|
+
*
|
|
160
|
+
* 安全边界(P0-1):`delivery:'user'`(到点以用户身份代发,绕过注入防护)只能
|
|
161
|
+
* 由人类显式输入的 `/later` 命令经 `trustedDelivery` **显式声明**——原始输入里的
|
|
162
|
+
* 同名字段一律被忽略。模型工具与 GUI 面板通道不传该选项,永远得到安全的
|
|
163
|
+
* `context` 注入形态;即使模型在工具参数里夹带 `delivery:'user'` 也无效。
|
|
164
|
+
*/
|
|
165
|
+
export interface UserScheduleCreateOptions {
|
|
166
|
+
/** 可信通道显式声明的投递形态;未提供或非 'user' 一律按安全默认 'context'。 */
|
|
167
|
+
readonly trustedDelivery?: UserScheduleDelivery;
|
|
168
|
+
}
|
|
169
|
+
/** `user_schedule_create` 核心实现。 */
|
|
170
|
+
export declare function userScheduleCreate(input: unknown, agent: Agent, ctx: Context, maxSchedules?: number, options?: UserScheduleCreateOptions, limits?: PromptLimits): Promise<UserScheduleCreateResult>;
|
|
171
|
+
/** `user_schedule_list` 核心实现。 */
|
|
172
|
+
export declare function userScheduleList(agent: Agent, ctx: Context): Promise<UserScheduleListResult>;
|
|
173
|
+
/** `user_schedule_delete` 核心实现。 */
|
|
174
|
+
export declare function userScheduleDelete(id: unknown, agent: Agent, ctx: Context): Promise<UserScheduleDeleteResult>;
|
|
175
|
+
/** `user_schedule_edit`(改内容)核心实现:删旧建新,保留原时刻与 delivery。 */
|
|
176
|
+
export declare function userScheduleEditPrompt(id: unknown, newPrompt: unknown, agent: Agent, ctx: Context, limits?: PromptLimits): Promise<UserScheduleCreateResult | UserScheduleError>;
|