Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions assets/seed/MANIFEST.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"bundle_version": "2026-09-28.1",
"bundle_version": "2026-10-04.1",
"description": "Versioned default ACECode global Skill, expert, and managed hook seed bundle reconciled at startup.",
"skills": [
{
Expand Down Expand Up @@ -46,9 +46,9 @@
},
{
"name": "acecode-desktop-usage",
"source_id": "acecode:acecode-desktop-usage@2026-09-09",
"source_id": "acecode:acecode-desktop-usage@2026-10-04",
"relative_path": "acecode/acecode-desktop-usage",
"skill_md_sha256": "5ace6b52f76f9fa95ccc2ec3c72231f9a4b159a5380d10aa2f638bca5a2b4d59"
"skill_md_sha256": "e67f13bd466c274840be46ab48bcffb8b4c06e61012010ab6cb2ae5670a64485"
},
{
"name": "vision-image-reader",
Expand All @@ -61,6 +61,12 @@
"source_id": "acecode:ai-theme@2026-09-15.3",
"relative_path": "acecode/ai-theme",
"skill_md_sha256": "db18caf8b4d9586139cc6eb9e8907cd5a263406acab5cd890a762992762d9014"
},
{
"name": "scheduled-task",
"source_id": "acecode:scheduled-task@2026-10-04",
"relative_path": "acecode/scheduled-task",
"skill_md_sha256": "89354de4dc007479bf5a39aba0179928f6f53b39ead451fddcdbb5c9a65b691e"
}
],
"experts": [
Expand Down
2 changes: 1 addition & 1 deletion assets/seed/seed.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2026-09-28.1
2026-10-04.1
2 changes: 1 addition & 1 deletion assets/seed/skills/acecode/acecode-desktop-usage/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ Desktop 内置命令菜单只提供一组聚焦的命令:
- 界面提供的有效时间范围。

Desktop 定时任务的权限选择少于普通任务,通常只提供默认审批或完全访问。保存后可以启用、
停用循环,并查看运行记录。除非调度设置明确要求立即运行,否则不要声称保存循环后会马上执行。
停用定时任务,并查看运行记录。除非调度设置明确要求立即运行,否则不要声称保存定时任务后会马上执行。

## 使用通知、托盘和更新

Expand Down
37 changes: 37 additions & 0 deletions assets/seed/skills/acecode/scheduled-task/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: scheduled-task
description: 通过自然语言创建 ACECode 内置定时任务。用于定时提醒、每天或每周执行、每隔一段时间检查、重复若干天等请求,以及“智能添加定时任务”入口。只讨论计划或立即执行普通任务时不创建定时任务。
---

# 创建定时任务

使用按需开放的内置工具 `create_scheduled_task` 创建任务,结果与页面“手动添加”相同。工具成功返回即完成创建;向用户说明任务、执行时间、时区及下次运行时间后结束本次回复,无需盯着、轮询或等待它执行。

## 整理用户意图

- 提取任务内容和执行时间。`X点`、`X天` 都是待用户填写的占位符,不能自行猜测或照字面创建。用简短问题补齐,必要时合并询问具体时刻、重复天数和会议内容。
- 用执行环境当前时间解析“明天”等相对日期;默认沿用 daemon 所在时区,远程连接或用户另指定时区时明确核对。不要硬编码今天、UTC 偏移或猜测 epoch 毫秒值;可用系统时间工具或本地日期计算命令计算。
- 名称保持简短;`prompt` 是到点要做的事。提醒任务应明确要求提醒用户,而不是让执行任务再次创建定时任务。不要把整段创建对话复制为执行提示词。
- 未指定模型时省略 `model_name`,沿用手动表单默认模型。纯提醒省略工作区;项目任务使用现有工作区的 `workspace_hash` 与 `workspace_cwd`,可用工作区查询工具核对。`use_worktree` 默认为 false,只在用户要求隔离时开启。

## 时间规则

`schedule` 复用现有手动表单:

- 一次性:`kind: "once"`,`once_at_ms` 为执行时刻的 epoch 毫秒。
- 每天/工作日/每周:`kind: "period"`,`period: "daily" | "workdays" | "weekly"`,提供 `hour`、`minute`;每周另提供 `weekdays`(0 为周日,1 为周一)。
- 固定间隔:`kind: "interval"`,`interval_value` 为正整数,`interval_unit: "minutes" | "hours" | "days"`;可提供 `anchor_ms`,省略时由工具取当前时间。
- 可选 `timezone_offset_minutes` 使用固定 UTC 偏移,省略时用 daemon 当前偏移。当前能力不承诺夏令时自动换算。
- 可选 `valid_from_ms` / `valid_until_ms` 指定有效期,边界包含在内。例如“从明天 9 点起,重复 3 天”使用每天 09:00,开始为明天 09:00,结束为第三天 09:00,确保恰有三次执行机会。留空字段应省略,不传 null。

## 创建与权限

调用 `create_scheduled_task` 时传 `name`、`prompt`、`schedule` 和必要的可选参数。工具会在保存前询问用户执行权限,默认推荐完全访问权限(YOLO),也可选默认权限。直接使用这次工具内询问,不提前重复询问,也不通过模型参数声称用户已确认。取消、插话或未作答时不会保存,按用户最新意图继续。

只有工具返回 `created: true` 才能告知“定时任务已创建”。失败时解释缺失参数、模型/工作区失效或时间冲突;调整后再创建。未提供工具的独立运行环境应说明当前入口不支持,不能伪称已创建,也不修改数据库或改用操作系统计划任务。

## 后续执行

任务在现有“定时任务”页面查看、修改、停用和删除;到期运行方式由调度器负责,不承诺每次新建或复用聊天。daemon 需运行,离线错过不补跑;同工作区已有定时任务运行时跳过该次。可使用截止时间或手动停用,停止正在执行的任务需打开对应执行会话。

普通任务沿用现有完成提示。监控类任务的执行提示词要保留用户的通知意图:无变化时保持安静,只在有实质变化、完成、失败或需要用户处理时报告;不要额外要求每次输出状态。
8 changes: 8 additions & 0 deletions docs/composer-tag-selection-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,11 @@ node scripts/test-composer-completion.mjs
- `materialize_context_items` 对 25 MiB 以内的栅格图带回字节;超限或读取失败退回路径引用,SVG、普通文件与文件夹不变。`composerFileIntake` 把带字节的图片条目还原成带来源路径标记的 File 走上传,同一手势里的其它条目照旧插 `@路径`。
- 对话记录中用户消息的图片附件改由气泡上方的缩略图条渲染,不再作为正文里的文件名按钮;只有图片的消息不画空气泡。
- 验证:`pnpm test`、`pnpm build` 通过;`DesktopContextItems.*` 8 项通过;在运行中的 Desktop 页面上确认旧会话的图片消息显示缩略图,并以桩桥接确认截图粘贴与「图片 + 普通文件」混合粘贴的输入框表现。`test-composer-file-drop.mjs` 需要 Playwright,本次未运行。

## 2026-10-04:tag 排版与普通方向键

此处覆盖前文历史行为:tag 为无背景的主题色文本,与正文使用相同字体、字号、行高和基线,仅稍加粗。选中时蓝底白字。普通左右键不再进入 tag 选择状态,而是一次越过一个 tag;Shift 和鼠标仍可选中,选中后复制、剪切、替换、删除和撤销保持原有行为。

- 生产 RichComposer 浏览器回归 89 项、InputBar 候选回归 16 项全部通过,包括连续 tag、空格、段落边界、RTL 和混合选择;定向模型测试、构建、OpenSpec 严格检查与差异检查通过。
- 本轮全量 `pnpm test` 被当前工作树其它改动的三个未登记静态文案阻断,详见 `openspec/changes/fix-composer-tag-selection/validation.md`。未改动无关文案或翻译目录。
- 验证平台为 Windows Chromium 生产组件 fixture;未重建或安装 Desktop/WebView2,未在真实输入法候选窗口人工验证。
41 changes: 33 additions & 8 deletions docs/daemon-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ update their transcript presentation.
| PUT | `/api/sessions/:id/permissions` | set session permission mode |
| GET | `/api/sessions/:id/model` | read session model state |
| POST | `/api/sessions/:id/model` | switch session model |
| POST | `/api/sessions/:id/reasoning` | set or reset the idle session's reasoning effort |
| POST | `/api/sessions/:id/reasoning` | set or reset session reasoning effort for the next model request |
| POST | `/api/sessions/:id/model/reload` | force reload the selected saved-model profile for one active session |
| POST | `/api/sessions/:id/fork` | fork a transcript prefix |
| POST | `/api/sessions/:id/file-checkpoints/:message_id/restore` | restore files to checkpoint |
Expand Down Expand Up @@ -1494,7 +1494,7 @@ records do not count as transcript messages; assistant (including empty
messages), tool, system and error messages prevent ordinary retry.

A completed manual stop persists a transcript-only system message with
`metadata.user_aborted: true` and `metadata.retry_user_message_id`. If that
`metadata.user_aborted: true`, `metadata.turn_id`, and `metadata.retry_user_message_id`. If that
marker is the final visible transcript entry, the backend may retry its
specified last user message even after partial assistant output or tool
results. A stop request alone, an interjection, or plain interruption text
Expand Down Expand Up @@ -1556,7 +1556,7 @@ returns `409` with the reason; so does posting directly to a mesh sub-agent
emits `session_updated {"swarm_mode"}`. See `docs/subagents.md` §9.

`client_message_id` is an optional non-empty string (maximum 256 bytes) used by
Desktop queued-input handoff. When accepted, it is preserved as
Desktop ordinary and queued-input handoff. When accepted, it is preserved as
`metadata.client_message_id` on the canonical user message so an optimistic
local item can reconcile with persistence and WebSocket replay. It does not
deduplicate backend execution; callers that omit it retain the existing behavior.
Expand Down Expand Up @@ -3206,8 +3206,13 @@ are unaffected. The override is persisted, restored on resume and inherited
by a fork. An explicit effort takes precedence over the saved reasoning token
budget; resetting the override restores that budget as well as the default.

Mutation runs under the worker's idle gate. An active turn or queued input
returns `409 SESSION_BUSY` without changing the selection. Malformed bodies,
Active turns and queued input accept changes. Each model request captures its
own provider snapshot: an in-flight request keeps its existing effort and is
not interrupted; the next request that captures its provider after the update
uses the new effort, including subsequent requests within the same turn.
Multiple successful changes before that boundary use the latest selection.
Failed persistence restores the prior provider and effort before another
request can capture them. Malformed bodies,
non-null selections for unsupported models and undeclared efforts return
`400 INVALID_REASONING_EFFORT`;
unknown sessions return `404 SESSION_NOT_FOUND`, unavailable model profiles
Expand Down Expand Up @@ -4947,11 +4952,22 @@ All client frames are JSON:
| `user_input` | `{session_id,text}` | queues plain user input |
| `decision` | `{session_id,request_id,choice}` | responds to permission request; `choice` is `allow`, `deny`, `allow_session`, `allow_scoped`, or `allow_remember` |
| `question_answer` | `{session_id,request_id,cancelled,answers}` | responds to AskUserQuestion |
| `abort` | `{session_id}` | aborts current turn |
| `abort` | `{session_id}` | requests cancellation of the current turn; completion is confirmed by terminal events |
| `ping` | `{}` | replies `{"type":"pong"}` |

`decision` uses `choice`, not `decision`, in the payload.

Sending `abort` does not mean the turn has already ended. Clients keep the
turn busy while showing a stopping state, then settle it on the matching
`busy_changed(false)` or `done` event. Terminal `turn_id` values must not end
a different active turn. The persisted `user_aborted` message confirms the
same termination notice even when tool messages arrive in between; older
records without `turn_id` are matched only within their user-turn boundary.
Queued input remains visible during cancellation. Previously queued messages
pause on a user stop; an explicit send or resume during stopping is honored
after completion. A client that cannot send the stop request must report the
failure and allow retry rather than displaying a completed stop.

For `bash`, `permission_request.args` retains the original tool arguments and
adds a server-generated `permission` object:

Expand Down Expand Up @@ -5179,13 +5195,22 @@ Resize uses `POST /api/pty/:id/resize`, not the WebSocket.

---

## 14. LOOP scheduling
## 14. Scheduled tasks

LOOP (Chinese UI: “循环”) is a daemon-owned scheduler. It persists to
Scheduled tasks (Chinese UI: “定时任务”, internal identifier: LOOP) is a daemon-owned scheduler. It persists to
`<acecode_dir>/scheduled-loops.sqlite3` and continues running without an open
browser. Clients configure friendly period/interval/once fields; the compiled
schedule expression is internal and is never returned by the API.

The daemon also registers the deferred built-in `create_scheduled_task` tool.
Loading the `scheduled-task` skill exposes it only in that conversation's model
requests. It shares request validation and persistence with the manual form.
The tool asks for execution permission before saving (YOLO is the recommended
choice; `default` is also available). Cancelled, unanswered, or automatically
timed-out choices do not create a task. Success returns `created`, `task`, and
`schedule_summary`; the task includes `id` and `next_run_at_ms`. The creating
conversation can finish immediately; execution follows the scheduler's policy.

Routes (all use the normal daemon auth and CORS rules):

| Method | Route | Purpose |
Expand Down
6 changes: 3 additions & 3 deletions docs/help-source/captures.json
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@
},
{
"file": "assets/screenshots/schedules-list.jpg",
"description": "循环列表的模板、频率、模型、启用入口与最近运行失败状态;现有循环保持停用",
"description": "定时任务列表的模板、频率、模型、启用入口与最近运行失败状态;现有定时任务保持停用",
"app": "process:N:\\Users\\shao\\acecode\\build\\Release\\acecode-desktop.exe",
"windowTitle": "ACECode",
"version": "0.9.11",
Expand All @@ -469,7 +469,7 @@
},
{
"file": "assets/screenshots/schedule-run-history.jpg",
"description": "循环真实运行记录:所选模型不可用导致停用,以及 daemon 未运行产生的已错过记录",
"description": "定时任务真实运行记录:所选模型不可用导致停用,以及 daemon 未运行产生的已错过记录",
"app": "process:N:\\Users\\shao\\acecode\\build\\Release\\acecode-desktop.exe",
"windowTitle": "ACECode",
"version": "0.9.11",
Expand All @@ -481,7 +481,7 @@
},
{
"file": "assets/screenshots/schedule-create-form.jpg",
"description": "添加循环表单:名称、工作空间、提示词、模型、执行频率和生效日期。此示例尚未保存。",
"description": "添加定时任务表单:名称、工作空间、提示词、模型、执行频率和生效日期。此示例尚未保存。",
"app": "process:N:\\Users\\shao\\acecode\\build\\Release\\acecode-desktop.exe",
"windowTitle": "ACECode",
"version": "0.9.11",
Expand Down
Loading
Loading