@downcity/plugins 1.0.12 → 1.0.21

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.
Files changed (72) hide show
  1. package/bin/chat/PROMPT.direct.d.ts +1 -1
  2. package/bin/chat/PROMPT.direct.d.ts.map +1 -1
  3. package/bin/chat/PROMPT.direct.js +1 -1
  4. package/bin/chat/PROMPT.direct.js.map +1 -1
  5. package/bin/chat/channels/BaseChatChannel.js +1 -1
  6. package/bin/chat/channels/BaseChatChannel.js.map +1 -1
  7. package/bin/chat/channels/qq/PROMPT.direct.d.ts +1 -1
  8. package/bin/chat/channels/qq/PROMPT.direct.d.ts.map +1 -1
  9. package/bin/chat/channels/qq/PROMPT.direct.js +1 -1
  10. package/bin/chat/channels/qq/PROMPT.direct.js.map +1 -1
  11. package/bin/chat/runtime/ChatPluginActionRegistry.js +8 -8
  12. package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
  13. package/bin/chat/runtime/ChatSendMetadata.d.ts +1 -1
  14. package/bin/chat/runtime/ChatSendMetadata.js +1 -1
  15. package/bin/chat/runtime/DirectDispatchParser.d.ts +2 -2
  16. package/bin/chat/runtime/DirectDispatchParser.js +2 -2
  17. package/bin/chat/types/DirectDispatch.d.ts +4 -4
  18. package/bin/chat/types/DirectDispatch.js +1 -1
  19. package/bin/contact/PROMPT.d.ts +1 -1
  20. package/bin/contact/PROMPT.d.ts.map +1 -1
  21. package/bin/contact/PROMPT.js +1 -1
  22. package/bin/contact/PROMPT.js.map +1 -1
  23. package/bin/contact/runtime/EndpointNotice.js +2 -2
  24. package/bin/contact/runtime/EndpointNotice.js.map +1 -1
  25. package/bin/shell/runtime/ShellRuntimeEnvironment.js +1 -1
  26. package/bin/shell/runtime/ShellRuntimeEnvironment.js.map +1 -1
  27. package/bin/skill/Command.d.ts +1 -1
  28. package/bin/skill/Command.js +2 -2
  29. package/bin/skill/Command.js.map +1 -1
  30. package/bin/skill/PROMPT.d.ts +1 -1
  31. package/bin/skill/PROMPT.d.ts.map +1 -1
  32. package/bin/skill/PROMPT.js +1 -1
  33. package/bin/skill/PROMPT.js.map +1 -1
  34. package/bin/task/Action.js +2 -2
  35. package/bin/task/Action.js.map +1 -1
  36. package/bin/task/PROMPT.d.ts +1 -1
  37. package/bin/task/PROMPT.d.ts.map +1 -1
  38. package/bin/task/PROMPT.js +1 -1
  39. package/bin/task/PROMPT.js.map +1 -1
  40. package/bin/tts/Plugin.js +3 -3
  41. package/bin/tts/Plugin.js.map +1 -1
  42. package/bin/tts/runtime/DependencyInstaller.d.ts +1 -1
  43. package/bin/tts/runtime/DependencyInstaller.js +1 -1
  44. package/bin/voice/runtime/DependencyInstaller.d.ts +1 -1
  45. package/bin/voice/runtime/DependencyInstaller.js +1 -1
  46. package/bin/voice/runtime/Transcriber.js +2 -2
  47. package/bin/voice/runtime/Transcriber.js.map +1 -1
  48. package/package.json +17 -17
  49. package/src/chat/PROMPT.direct.ts +1 -1
  50. package/src/chat/PROMPT.direct.ts.txt +6 -6
  51. package/src/chat/channels/BaseChatChannel.ts +1 -1
  52. package/src/chat/channels/qq/PROMPT.direct.ts +1 -1
  53. package/src/chat/channels/qq/PROMPT.direct.ts.txt +1 -1
  54. package/src/chat/runtime/ChatPluginActionRegistry.ts +8 -8
  55. package/src/chat/runtime/ChatSendMetadata.ts +1 -1
  56. package/src/chat/runtime/DirectDispatchParser.ts +2 -2
  57. package/src/chat/types/DirectDispatch.ts +4 -4
  58. package/src/contact/PROMPT.ts +1 -1
  59. package/src/contact/PROMPT.ts.txt +11 -11
  60. package/src/contact/runtime/EndpointNotice.ts +2 -2
  61. package/src/shell/runtime/ShellRuntimeEnvironment.ts +1 -1
  62. package/src/skill/Command.ts +2 -2
  63. package/src/skill/PROMPT.ts +1 -1
  64. package/src/skill/PROMPT.ts.txt +2 -2
  65. package/src/task/Action.ts +2 -2
  66. package/src/task/PROMPT.ts +1 -1
  67. package/src/task/PROMPT.ts.txt +9 -9
  68. package/src/tts/Plugin.ts +3 -3
  69. package/src/tts/runtime/DependencyInstaller.ts +1 -1
  70. package/src/voice/runtime/DependencyInstaller.ts +1 -1
  71. package/src/voice/runtime/Transcriber.ts +2 -2
  72. package/tsconfig.json +1 -0
@@ -3,21 +3,21 @@ Contact plugin
3
3
  contact plugin 用来管理和其他 agent 的联系方式。一个 contact 代表一个已建立联系的远端 agent,并固定拥有一条长期对话历史。contact 可以是单向的:只要本 agent 能访问对方,就可以 check、chat、share。
4
4
 
5
5
  可用命令:
6
- - `studio contact link`:生成一次性联系码,交给另一个 agent。
7
- - `studio contact approve <code>`:使用对方给的联系码建立 contact。
8
- - `studio contact list`:查看已保存的 agent 联系方式。
9
- - `studio contact check <contact>` / `studio contact check --to <ip:port>`:检查对方是否在线可用。
10
- - `studio contact chat --to <contact> "<message>"`:和某个 agent 对话。
11
- - `studio contact share --to <contact> --text ... | --link ... | <path...>`:分享文本、链接、文件或目录。
12
- - `studio contact inbox`:查看收到的分享。
13
- - `studio contact receive <share_id>`:接收某条分享。
6
+ - `town contact link`:生成一次性联系码,交给另一个 agent。
7
+ - `town contact approve <code>`:使用对方给的联系码建立 contact。
8
+ - `town contact list`:查看已保存的 agent 联系方式。
9
+ - `town contact check <contact>` / `town contact check --to <ip:port>`:检查对方是否在线可用。
10
+ - `town contact chat --to <contact> "<message>"`:和某个 agent 对话。
11
+ - `town contact share --to <contact> --text ... | --link ... | <path...>`:分享文本、链接、文件或目录。
12
+ - `town contact inbox`:查看收到的分享。
13
+ - `town contact receive <share_id>`:接收某条分享。
14
14
 
15
15
  边界:
16
16
  - chat 用于对话,share 用于资料交接。
17
- - `studio contact link` 返回中的 notes 会说明联系码适合本机、局域网还是公网 agent 使用;本地 localhost 联系码不能交给 server agent approve。
17
+ - `town contact link` 返回中的 notes 会说明联系码适合本机、局域网还是公网 agent 使用;本地 localhost 联系码不能交给 server agent approve。
18
18
  - public-looking endpoint 仍可能被防火墙/NAT 阻断;以返回的 notes 为准,不要承诺公网一定可达。
19
- - `studio start` 会自动写入 `DOWNCITY_PUBLIC_HOST` 供 contact link 使用;这不是要求用户手动配置的 token 或 endpoint。
20
- - `studio contact approve` 会先建立单向关系,再由对方主动 ping 回本 agent,ping 成功才升级为 bidirectional。
19
+ - `town start` 会自动写入 `DOWNCITY_PUBLIC_HOST` 供 contact link 使用;这不是要求用户手动配置的 token 或 endpoint。
20
+ - `town contact approve` 会先建立单向关系,再由对方主动 ping 回本 agent,ping 成功才升级为 bidirectional。
21
21
  - local/private agent 连接 public agent 时通常只能 outbound-only,不要说成双向。
22
22
  - contact token 由 link/approve 自动交换;不要要求用户手动配置 token 环境变量。
23
23
  - `Contact link not found` 表示请求打到的 agent runtime 没有这条 link 记录,优先检查 endpoint/端口/agent 是否一致;过期会明确返回 `Contact link expired`。
@@ -60,7 +60,7 @@ export function buildContactLinkNotes(params: {
60
60
  if (reachability === "loopback") {
61
61
  return [
62
62
  "This link endpoint is local-only. Only an agent on the same machine can approve it; a server agent cannot approve a link generated by this local agent.",
63
- "Start city from a reachable environment before generating a new link; studio start automatically writes the public host used by contact links when it can detect one.",
63
+ "Start city from a reachable environment before generating a new link; town start automatically writes the public host used by contact links when it can detect one.",
64
64
  ];
65
65
  }
66
66
  if (reachability === "private") {
@@ -118,7 +118,7 @@ export function buildContactApproveNotes(params: {
118
118
  );
119
119
  } else {
120
120
  notes.push(
121
- "This contact is outbound-only from this side: this agent can call the peer, but the peer cannot call back unless this agent was started with a reachable address that studio start can provide to contact.",
121
+ "This contact is outbound-only from this side: this agent can call the peer, but the peer cannot call back unless this agent was started with a reachable address that town start can provide to contact.",
122
122
  );
123
123
  }
124
124
  return notes;
@@ -34,7 +34,7 @@ export function buildShellEnv(context: AgentContext): NodeJS.ProcessEnv {
34
34
  const agentId = configuredAgentId || (agentPath ? path.basename(agentPath) : "");
35
35
 
36
36
  // 关键点(中文)
37
- // - agent 自己在 shell 里执行 `studio <service> ...` 时,也需要显式知道“当前 agent 是谁”。
37
+ // - agent 自己在 shell 里执行 `town <service> ...` 时,也需要显式知道“当前 agent 是谁”。
38
38
  // - 否则 service CLI 会退回到当前终端 cwd / registry 猜测,在多 agent 或外部工作目录下
39
39
  // 很容易把请求发到错误项目,最终误报 “Agent server 没启动”。
40
40
  if (agentPath) env.DC_AGENT_PATH = agentPath;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `studio skill` 命令 helper。
2
+ * `town skill` 命令 helper。
3
3
  *
4
4
  * 设计目标(中文)
5
5
  * - 尽量不自建 registry:直接复用社区的 `npx skills` 生态(find/install)。
@@ -79,7 +79,7 @@ export async function skillListCommand(cwd: string = "."): Promise<void> {
79
79
  const shipJson = path.join(projectRoot, "downcity.json");
80
80
  if (!fs.existsSync(shipJson)) {
81
81
  throw new Error(
82
- `downcity.json not found at ${shipJson}. Run "studio agent create" first or pass the correct path.`,
82
+ `downcity.json not found at ${shipJson}. Run "town agent create" first or pass the correct path.`,
83
83
  );
84
84
  }
85
85
 
@@ -4,6 +4,6 @@
4
4
  */
5
5
 
6
6
  // Source: src/skill/PROMPT.ts.txt
7
- const TEXT_MODULE_CONTENT = "# Skill Plugin\n\nskill 是你拥有的技能。用户的提出的需求和任务,你都需要先考虑利用相关的skill来高质量的完成。\n\n\n## 使用\n\n使用技能时需要首先通过 `studio skill lookup <name>` 命令载入对应的技能内容。\n\n你也可以使用 `studio skill --help` 命令对skill进行其他操作。比如 `list`, `find`, `install`等等。\n";
7
+ const TEXT_MODULE_CONTENT = "# Skill Plugin\n\nskill 是你拥有的技能。用户的提出的需求和任务,你都需要先考虑利用相关的skill来高质量的完成。\n\n\n## 使用\n\n使用技能时需要首先通过 `town skill lookup <name>` 命令载入对应的技能内容。\n\n你也可以使用 `town skill --help` 命令对skill进行其他操作。比如 `list`, `find`, `install`等等。\n";
8
8
 
9
9
  export default TEXT_MODULE_CONTENT;
@@ -5,6 +5,6 @@ skill 是你拥有的技能。用户的提出的需求和任务,你都需要
5
5
 
6
6
  ## 使用
7
7
 
8
- 使用技能时需要首先通过 `studio skill lookup <name>` 命令载入对应的技能内容。
8
+ 使用技能时需要首先通过 `town skill lookup <name>` 命令载入对应的技能内容。
9
9
 
10
- 你也可以使用 `studio skill --help` 命令对skill进行其他操作。比如 `list`, `find`, `install`等等。
10
+ 你也可以使用 `town skill --help` 命令对skill进行其他操作。比如 `list`, `find`, `install`等等。
@@ -75,7 +75,7 @@ function buildDefaultTaskBody(): string {
75
75
  "",
76
76
  "- 最终输出直接写结果本身,不要包多余寒暄,不要粘贴冗长日志。",
77
77
  "- 需要结构时,优先使用短标题、要点列表、表格或 JSON 等稳定格式。",
78
- "- 默认不要在正文里重复调用 `studio chat send`;系统会自动发送最终结果。",
78
+ "- 默认不要在正文里重复调用 `town chat send`;系统会自动发送最终结果。",
79
79
  "",
80
80
  "# 触发与状态建议",
81
81
  "",
@@ -87,7 +87,7 @@ function buildDefaultTaskBody(): string {
87
87
  "",
88
88
  "- 当前是独立 task 上下文,不要假设仍处在原始聊天回合里。",
89
89
  "- 尽量使用可审计的方式:关键中间产物写入 `./.downcity/task/<title>/<timestamp>/` 下的 markdown 文件。",
90
- "- 如果任务明确要求跨会话、跨平台或发送额外通知,再显式调用 `studio chat send`。",
90
+ "- 如果任务明确要求跨会话、跨平台或发送额外通知,再显式调用 `town chat send`。",
91
91
  "",
92
92
  ].join("\n");
93
93
  }
@@ -4,6 +4,6 @@
4
4
  */
5
5
 
6
6
  // Source: src/task/PROMPT.ts.txt
7
- const TEXT_MODULE_CONTENT = "# Task Plugin\n\n你可以通过 `task` plugin 管理任务定义、执行、调度与状态控制。\n\n## 任务模型\n\n每个任务定义在 `./.downcity/task/<title>/task.md`,包含:\n- frontmatter(结构化字段)\n- body(任务正文)\n\nfrontmatter 核心字段:\n- `title`:任务唯一标识(唯一)\n- `description`:任务描述\n- `when`:触发条件,支持:`@manual` / cron / `time:<ISO8601-with-timezone>`\n- `sessionId`:任务执行会话\n- `status`:`enabled|paused|disabled`\n- `kind`:`agent|script`(默认 `agent`)\n\n执行时会产生 run 目录:\n- `./.downcity/task/<title>/<timestamp>/`\n\n常见产物:\n- `input.md`\n- `output.md`(本次任务的最终输出正文)\n- `result.md`(执行摘要)\n- `run.json`\n- `run-progress.json`\n- `dialogue.md` / `dialogue.json`(agent 多轮)\n- `error.md`(失败时)\n\n## 执行类型(kind)\n\n1. `kind=agent`\n- 将正文交给 agent 执行\n- 默认单轮完成;仅当 frontmatter 显式设置 `review: true` 时启用模拟用户多轮复核\n- 适合研究、分析、报告生成\n\n2. `kind=script`\n- 将正文当作 shell 脚本执行\n- 正文不能为空,必须是可执行脚本\n\n## 可用 action\n\n- `list`\n- `create`\n- `run`\n- `delete`\n- `update`\n- `status`\n- `enable`\n- `disable`\n\n## CLI 示例\n\n- `studio task list [--status enabled|paused|disabled]`\n- `studio task create --title '...' --description '...' --session-id <sessionId> [--when '@manual'] [--kind agent|script] [--status ...|--activate]`\n- `studio task run <title> [--reason '...']`\n- `studio task update <title> [--title ...] [--description ...] [--when ...] [--status ...|--activate] [--session-id ...]`\n- `studio task delete <title>`\n\n## 关键约束\n\n- `title` 唯一;create 去重仅按 `title` 精确匹配。\n- `when=time:...` 触发后会自动置为 `paused`,并回退为 `when=@manual`。\n- `run` 为异步受理:立即返回 `accepted=true`、`message`、`executionId`;调用方应把它视为“任务已进入后台执行,结果会自动通过 chat plugin runtime 发送,当前流程无需阻塞等待”。\n- 如果 `run` 返回 `accepted=true`:\n - 不要手动把 task 产出再转发给用户。\n - 不要主动读取 run 目录、`run-progress.json`、`output.md` 做轮询。\n - 只有当用户明确要求排查、查看产物或确认执行细节时,才进入 run 目录检查。\n- agent 任务默认只要求产生有效输出;仅当任务正文明确要求外发时,才应发送到外部 channel。\n\n## 如何设计 task 正文\n\n### agent task 推荐结构\n\n建议正文至少包含这些标题:\n\n```md\n# 任务目标\n\n- 这次任务要交付什么最终结果\n\n# 背景与输入\n\n- 数据来源、范围、约束、参考材料\n\n# 执行步骤\n\n1. 先做什么\n2. 再做什么\n3. 关键中间产物落在哪里\n\n# 输出要求\n\n- 最终结果用什么格式返回\n- 是否需要表格 / JSON / Markdown\n- 不要包含什么内容\n\n# 触发与状态建议\n\n- 这个任务为什么适合 `@manual` / cron / `time:...`\n- 当前应该是 `paused` 还是 `enabled`\n\n# 注意事项\n\n- 风险、边界、不要做什么\n```\n\n### agent task 正文编写约束\n\n- task 正文必须像一份“交付合同”,让另一个执行器拿到后可以直接执行,不依赖当前聊天语境补全含义。\n- `# 任务目标` 必须写清楚最终要交付什么,不要只写“看一下”“研究一下”“处理一下”这类模糊目标。\n- `# 背景与输入` 必须写清来源、范围、对象、时间、限制条件;不要假设执行器还能看到原始聊天上下文。\n- `# 执行步骤` 应描述任务流程,不应描述 task 管理动作;不要写“先检查有没有同名任务”“再创建任务”“然后触发任务”。\n- `# 输出要求` 必须清楚声明最终成品的格式、结构、语气、长度,以及“不要输出什么”。\n- 要明确写出:**最后一条 assistant 返回会被直接写入 `output.md` 并发送给用户**;因此最终回答必须直接等于成品内容。\n- 内容生成类任务(如日报、提醒、晨读、摘要、报告)必须明确要求“最终输出直接是成品正文”,不要让执行器输出过程说明。\n- 如果任务要把结果发给用户,正文应要求“输出可直接发送的正文内容”,而不是要求执行器解释自己已经发送了什么。\n- 除非确有需要,不要在正文中要求执行器复述 task title、sessionId、执行时间、状态等元信息。\n- 正文中的约束要可执行、可判断,尽量避免“适当”“尽量”“看情况”这类弱约束词。\n- 不要把创建 task、更新 task、查看 task 状态、确认 task 是否存在等管理动作写进正文;这些属于 task plugin 的职责,不属于 task 正文交付物。\n\n### agent task 正文禁止写法\n\n- 不要把正文写成聊天回复口吻,例如:\n - “我来为你……”\n - “首先让我……”\n - “我先检查一下……”\n - “我看到已经有一个同名任务……”\n- 不要把正文写成任务管理说明,例如:\n - “如果任务已存在则更新,否则创建”\n - “先 list 再 run”\n - “完成后告诉用户任务已启动”\n- 不要把正文写成状态汇报模板,例如:\n - “任务状态总结”\n - “已发送 / 已完成 / 已更新”\n - “当前任务配置如下”\n- 不要只描述动作,不描述成品,例如:\n - “去搜集一些资料”\n - “生成一个内容看看”\n - “做完后反馈结果”\n- 不要把正文写成依赖当前上下文的指代,例如:\n - “按上面说的做”\n - “继续刚才那个”\n - “把这个发出去”\n\n### 如何判断正文写得对不对\n\n- 如果把 task 正文单独复制出来给另一个 agent,它仍然能理解任务目标、输入、步骤和交付物,说明正文合格。\n- 如果最终输出章节删掉后,正文只剩“去做一下”式描述,说明正文不合格。\n- 如果正文更像“创建/更新任务的操作说明”,而不是“任务执行说明”,说明分层错了,必须重写。\n- 如果正文天然会诱导执行器输出过程汇报,而不是最终成品,说明 `# 输出要求` 写得不够强,必须补充禁止项。\n\n### script task 推荐结构\n\n- 正文必须是纯 shell 脚本,不要混入解释性自然语言。\n- 开头尽量写注释说明脚本目的、输入依赖、失败条件。\n- 输出保持稳定,便于直接作为最终结果发送给用户。\n- 如需生成文件,写到 run 目录或明确的项目路径。\n\n### 输出设计原则\n\n- task 完成后,系统会自动把**最终结果正文**通过 chat plugin runtime 的 `send` 发回 `sessionId` 绑定的 chat。\n- 当前实现采用最简规则:**最后一条 assistant 返回**会被直接视为最终结果正文,并写入 `output.md`。\n- 因此正文里的“输出要求”要面向最终用户阅读,不要只写给开发者看。\n- 对于面向用户的 agent task,正文应要求“最后一条 assistant 返回直接输出最终交付物本身”,不要让执行器在最后回答里输出自己如何创建、检查、更新、触发或发送任务。\n- 如果任务是内容生成类(例如日报、提醒、晨读、摘要),最后输出应直接是那段内容本身,不要附带“我来为你处理”“任务已发送”“任务状态总结”等过程汇报。\n- 默认不要在正文里再次要求执行器调用 `studio chat send`。\n- 只有在“跨会话发送”“额外抄送”“多渠道通知”这类场景下,才显式要求 `studio chat send`。\n\n### `when` / `status` 怎么选\n\n- task 创建默认就是 `status=enabled`;如果还在试任务、容易失败、需要人工确认,再显式切到 `paused`。\n- 已经验证稳定、需要自动运行:直接使用 cron + `status=enabled`。\n- 明确只执行一次:使用 `time:<带时区 ISO 时间>`;执行后系统会自动回退到 `@manual` + `paused`。\n- 如果用户只是“先存起来以后再跑”,不要直接启用调度。\n\n## 正文模板\n\n### agent 模板\n\n```md\n# 任务目标\n\n- 产出一份可直接发给用户的最终结果。\n\n# 背景与输入\n\n- 在这里补充上下文、文件、链接、范围和假设。\n\n# 执行步骤\n\n1. 理解任务目标与完成标准。\n2. 收集必要信息并执行任务。\n3. 把关键中间产物写入 run 目录。\n4. 输出最终结果正文。\n\n# 输出要求\n\n- 最后一条 assistant 返回直接作为最终结果,不要附带冗长日志。\n- 最后一条 assistant 返回直接输出交付物本身,不要输出任务管理过程、发送过程或状态汇报。\n- 不要使用“我来为你…… / 首先让我…… / 已发送……”这类元话术。\n- 默认不要再次调用 `studio chat send`。\n\n# 触发与状态建议\n\n- 默认创建后立即启用;如果只是先保存草稿或等待人工确认,再改成 `paused`。\n\n# 注意事项\n\n- 仅在明确需要跨会话或额外通知时,才调用 `studio chat send`。\n```\n\n### script 模板\n\n```bash\n# 任务目标:一句话说明脚本要做什么\n# 输入依赖:列出环境变量、文件、命令依赖\n# 失败条件:列出应该 exit 1 的情况\n\nset -euo pipefail\n\n# 1. 准备输入\n\n# 2. 执行主逻辑\n\n# 3. 输出最终结果(这段输出会被直接发送给用户)\n```\n\n## 建议\n\n- 先 `list`,再 `create`/`update`。\n- 简单内容生成任务优先保持默认单轮;只有确实需要“先生成、再复核、再修订”时再设置 `review: true`。\n- script 任务正文保持纯脚本,不要混入冗余自然语言。\n- 如果用户只是先存起来以后再跑,创建后显式设成 `paused`;否则保持默认启用。\n- task 正文要写“最终结果长什么样”,不要只写“去做一下看看”。\n- 对内容生成任务,要明确写“最后一条 assistant 返回只能是成品正文”,避免执行器把过程说明误当成最终结果。\n";
7
+ const TEXT_MODULE_CONTENT = "# Task Plugin\n\n你可以通过 `task` plugin 管理任务定义、执行、调度与状态控制。\n\n## 任务模型\n\n每个任务定义在 `./.downcity/task/<title>/task.md`,包含:\n- frontmatter(结构化字段)\n- body(任务正文)\n\nfrontmatter 核心字段:\n- `title`:任务唯一标识(唯一)\n- `description`:任务描述\n- `when`:触发条件,支持:`@manual` / cron / `time:<ISO8601-with-timezone>`\n- `sessionId`:任务执行会话\n- `status`:`enabled|paused|disabled`\n- `kind`:`agent|script`(默认 `agent`)\n\n执行时会产生 run 目录:\n- `./.downcity/task/<title>/<timestamp>/`\n\n常见产物:\n- `input.md`\n- `output.md`(本次任务的最终输出正文)\n- `result.md`(执行摘要)\n- `run.json`\n- `run-progress.json`\n- `dialogue.md` / `dialogue.json`(agent 多轮)\n- `error.md`(失败时)\n\n## 执行类型(kind)\n\n1. `kind=agent`\n- 将正文交给 agent 执行\n- 默认单轮完成;仅当 frontmatter 显式设置 `review: true` 时启用模拟用户多轮复核\n- 适合研究、分析、报告生成\n\n2. `kind=script`\n- 将正文当作 shell 脚本执行\n- 正文不能为空,必须是可执行脚本\n\n## 可用 action\n\n- `list`\n- `create`\n- `run`\n- `delete`\n- `update`\n- `status`\n- `enable`\n- `disable`\n\n## CLI 示例\n\n- `town task list [--status enabled|paused|disabled]`\n- `town task create --title '...' --description '...' --session-id <sessionId> [--when '@manual'] [--kind agent|script] [--status ...|--activate]`\n- `town task run <title> [--reason '...']`\n- `town task update <title> [--title ...] [--description ...] [--when ...] [--status ...|--activate] [--session-id ...]`\n- `town task delete <title>`\n\n## 关键约束\n\n- `title` 唯一;create 去重仅按 `title` 精确匹配。\n- `when=time:...` 触发后会自动置为 `paused`,并回退为 `when=@manual`。\n- `run` 为异步受理:立即返回 `accepted=true`、`message`、`executionId`;调用方应把它视为“任务已进入后台执行,结果会自动通过 chat plugin runtime 发送,当前流程无需阻塞等待”。\n- 如果 `run` 返回 `accepted=true`:\n - 不要手动把 task 产出再转发给用户。\n - 不要主动读取 run 目录、`run-progress.json`、`output.md` 做轮询。\n - 只有当用户明确要求排查、查看产物或确认执行细节时,才进入 run 目录检查。\n- agent 任务默认只要求产生有效输出;仅当任务正文明确要求外发时,才应发送到外部 channel。\n\n## 如何设计 task 正文\n\n### agent task 推荐结构\n\n建议正文至少包含这些标题:\n\n```md\n# 任务目标\n\n- 这次任务要交付什么最终结果\n\n# 背景与输入\n\n- 数据来源、范围、约束、参考材料\n\n# 执行步骤\n\n1. 先做什么\n2. 再做什么\n3. 关键中间产物落在哪里\n\n# 输出要求\n\n- 最终结果用什么格式返回\n- 是否需要表格 / JSON / Markdown\n- 不要包含什么内容\n\n# 触发与状态建议\n\n- 这个任务为什么适合 `@manual` / cron / `time:...`\n- 当前应该是 `paused` 还是 `enabled`\n\n# 注意事项\n\n- 风险、边界、不要做什么\n```\n\n### agent task 正文编写约束\n\n- task 正文必须像一份“交付合同”,让另一个执行器拿到后可以直接执行,不依赖当前聊天语境补全含义。\n- `# 任务目标` 必须写清楚最终要交付什么,不要只写“看一下”“研究一下”“处理一下”这类模糊目标。\n- `# 背景与输入` 必须写清来源、范围、对象、时间、限制条件;不要假设执行器还能看到原始聊天上下文。\n- `# 执行步骤` 应描述任务流程,不应描述 task 管理动作;不要写“先检查有没有同名任务”“再创建任务”“然后触发任务”。\n- `# 输出要求` 必须清楚声明最终成品的格式、结构、语气、长度,以及“不要输出什么”。\n- 要明确写出:**最后一条 assistant 返回会被直接写入 `output.md` 并发送给用户**;因此最终回答必须直接等于成品内容。\n- 内容生成类任务(如日报、提醒、晨读、摘要、报告)必须明确要求“最终输出直接是成品正文”,不要让执行器输出过程说明。\n- 如果任务要把结果发给用户,正文应要求“输出可直接发送的正文内容”,而不是要求执行器解释自己已经发送了什么。\n- 除非确有需要,不要在正文中要求执行器复述 task title、sessionId、执行时间、状态等元信息。\n- 正文中的约束要可执行、可判断,尽量避免“适当”“尽量”“看情况”这类弱约束词。\n- 不要把创建 task、更新 task、查看 task 状态、确认 task 是否存在等管理动作写进正文;这些属于 task plugin 的职责,不属于 task 正文交付物。\n\n### agent task 正文禁止写法\n\n- 不要把正文写成聊天回复口吻,例如:\n - “我来为你……”\n - “首先让我……”\n - “我先检查一下……”\n - “我看到已经有一个同名任务……”\n- 不要把正文写成任务管理说明,例如:\n - “如果任务已存在则更新,否则创建”\n - “先 list 再 run”\n - “完成后告诉用户任务已启动”\n- 不要把正文写成状态汇报模板,例如:\n - “任务状态总结”\n - “已发送 / 已完成 / 已更新”\n - “当前任务配置如下”\n- 不要只描述动作,不描述成品,例如:\n - “去搜集一些资料”\n - “生成一个内容看看”\n - “做完后反馈结果”\n- 不要把正文写成依赖当前上下文的指代,例如:\n - “按上面说的做”\n - “继续刚才那个”\n - “把这个发出去”\n\n### 如何判断正文写得对不对\n\n- 如果把 task 正文单独复制出来给另一个 agent,它仍然能理解任务目标、输入、步骤和交付物,说明正文合格。\n- 如果最终输出章节删掉后,正文只剩“去做一下”式描述,说明正文不合格。\n- 如果正文更像“创建/更新任务的操作说明”,而不是“任务执行说明”,说明分层错了,必须重写。\n- 如果正文天然会诱导执行器输出过程汇报,而不是最终成品,说明 `# 输出要求` 写得不够强,必须补充禁止项。\n\n### script task 推荐结构\n\n- 正文必须是纯 shell 脚本,不要混入解释性自然语言。\n- 开头尽量写注释说明脚本目的、输入依赖、失败条件。\n- 输出保持稳定,便于直接作为最终结果发送给用户。\n- 如需生成文件,写到 run 目录或明确的项目路径。\n\n### 输出设计原则\n\n- task 完成后,系统会自动把**最终结果正文**通过 chat plugin runtime 的 `send` 发回 `sessionId` 绑定的 chat。\n- 当前实现采用最简规则:**最后一条 assistant 返回**会被直接视为最终结果正文,并写入 `output.md`。\n- 因此正文里的“输出要求”要面向最终用户阅读,不要只写给开发者看。\n- 对于面向用户的 agent task,正文应要求“最后一条 assistant 返回直接输出最终交付物本身”,不要让执行器在最后回答里输出自己如何创建、检查、更新、触发或发送任务。\n- 如果任务是内容生成类(例如日报、提醒、晨读、摘要),最后输出应直接是那段内容本身,不要附带“我来为你处理”“任务已发送”“任务状态总结”等过程汇报。\n- 默认不要在正文里再次要求执行器调用 `town chat send`。\n- 只有在“跨会话发送”“额外抄送”“多渠道通知”这类场景下,才显式要求 `town chat send`。\n\n### `when` / `status` 怎么选\n\n- task 创建默认就是 `status=enabled`;如果还在试任务、容易失败、需要人工确认,再显式切到 `paused`。\n- 已经验证稳定、需要自动运行:直接使用 cron + `status=enabled`。\n- 明确只执行一次:使用 `time:<带时区 ISO 时间>`;执行后系统会自动回退到 `@manual` + `paused`。\n- 如果用户只是“先存起来以后再跑”,不要直接启用调度。\n\n## 正文模板\n\n### agent 模板\n\n```md\n# 任务目标\n\n- 产出一份可直接发给用户的最终结果。\n\n# 背景与输入\n\n- 在这里补充上下文、文件、链接、范围和假设。\n\n# 执行步骤\n\n1. 理解任务目标与完成标准。\n2. 收集必要信息并执行任务。\n3. 把关键中间产物写入 run 目录。\n4. 输出最终结果正文。\n\n# 输出要求\n\n- 最后一条 assistant 返回直接作为最终结果,不要附带冗长日志。\n- 最后一条 assistant 返回直接输出交付物本身,不要输出任务管理过程、发送过程或状态汇报。\n- 不要使用“我来为你…… / 首先让我…… / 已发送……”这类元话术。\n- 默认不要再次调用 `town chat send`。\n\n# 触发与状态建议\n\n- 默认创建后立即启用;如果只是先保存草稿或等待人工确认,再改成 `paused`。\n\n# 注意事项\n\n- 仅在明确需要跨会话或额外通知时,才调用 `town chat send`。\n```\n\n### script 模板\n\n```bash\n# 任务目标:一句话说明脚本要做什么\n# 输入依赖:列出环境变量、文件、命令依赖\n# 失败条件:列出应该 exit 1 的情况\n\nset -euo pipefail\n\n# 1. 准备输入\n\n# 2. 执行主逻辑\n\n# 3. 输出最终结果(这段输出会被直接发送给用户)\n```\n\n## 建议\n\n- 先 `list`,再 `create`/`update`。\n- 简单内容生成任务优先保持默认单轮;只有确实需要“先生成、再复核、再修订”时再设置 `review: true`。\n- script 任务正文保持纯脚本,不要混入冗余自然语言。\n- 如果用户只是先存起来以后再跑,创建后显式设成 `paused`;否则保持默认启用。\n- task 正文要写“最终结果长什么样”,不要只写“去做一下看看”。\n- 对内容生成任务,要明确写“最后一条 assistant 返回只能是成品正文”,避免执行器把过程说明误当成最终结果。\n";
8
8
 
9
9
  export default TEXT_MODULE_CONTENT;
@@ -52,11 +52,11 @@ frontmatter 核心字段:
52
52
 
53
53
  ## CLI 示例
54
54
 
55
- - `studio task list [--status enabled|paused|disabled]`
56
- - `studio task create --title '...' --description '...' --session-id <sessionId> [--when '@manual'] [--kind agent|script] [--status ...|--activate]`
57
- - `studio task run <title> [--reason '...']`
58
- - `studio task update <title> [--title ...] [--description ...] [--when ...] [--status ...|--activate] [--session-id ...]`
59
- - `studio task delete <title>`
55
+ - `town task list [--status enabled|paused|disabled]`
56
+ - `town task create --title '...' --description '...' --session-id <sessionId> [--when '@manual'] [--kind agent|script] [--status ...|--activate]`
57
+ - `town task run <title> [--reason '...']`
58
+ - `town task update <title> [--title ...] [--description ...] [--when ...] [--status ...|--activate] [--session-id ...]`
59
+ - `town task delete <title>`
60
60
 
61
61
  ## 关键约束
62
62
 
@@ -165,8 +165,8 @@ frontmatter 核心字段:
165
165
  - 因此正文里的“输出要求”要面向最终用户阅读,不要只写给开发者看。
166
166
  - 对于面向用户的 agent task,正文应要求“最后一条 assistant 返回直接输出最终交付物本身”,不要让执行器在最后回答里输出自己如何创建、检查、更新、触发或发送任务。
167
167
  - 如果任务是内容生成类(例如日报、提醒、晨读、摘要),最后输出应直接是那段内容本身,不要附带“我来为你处理”“任务已发送”“任务状态总结”等过程汇报。
168
- - 默认不要在正文里再次要求执行器调用 `studio chat send`。
169
- - 只有在“跨会话发送”“额外抄送”“多渠道通知”这类场景下,才显式要求 `studio chat send`。
168
+ - 默认不要在正文里再次要求执行器调用 `town chat send`。
169
+ - 只有在“跨会话发送”“额外抄送”“多渠道通知”这类场景下,才显式要求 `town chat send`。
170
170
 
171
171
  ### `when` / `status` 怎么选
172
172
 
@@ -200,7 +200,7 @@ frontmatter 核心字段:
200
200
  - 最后一条 assistant 返回直接作为最终结果,不要附带冗长日志。
201
201
  - 最后一条 assistant 返回直接输出交付物本身,不要输出任务管理过程、发送过程或状态汇报。
202
202
  - 不要使用“我来为你…… / 首先让我…… / 已发送……”这类元话术。
203
- - 默认不要再次调用 `studio chat send`。
203
+ - 默认不要再次调用 `town chat send`。
204
204
 
205
205
  # 触发与状态建议
206
206
 
@@ -208,7 +208,7 @@ frontmatter 核心字段:
208
208
 
209
209
  # 注意事项
210
210
 
211
- - 仅在明确需要跨会话或额外通知时,才调用 `studio chat send`。
211
+ - 仅在明确需要跨会话或额外通知时,才调用 `town chat send`。
212
212
  ```
213
213
 
214
214
  ### script 模板
package/src/tts/Plugin.ts CHANGED
@@ -493,13 +493,13 @@ function createTtsPluginDefinition(plugin: Plugin): Plugin {
493
493
  "# TTS Plugin",
494
494
  "The agent can call the tts plugin to synthesize speech audio from plain text.",
495
495
  "Typical usage flow:",
496
- "1. Check availability with `studio tts status` when you need to confirm whether the plugin and model are ready.",
497
- "2. Generate audio with `studio tts synthesize <text>`.",
496
+ "1. Check availability with `town tts status` when you need to confirm whether the plugin and model are ready.",
497
+ "2. Generate audio with `town tts synthesize <text>`.",
498
498
  "3. Optionally override synthesis parameters with `--voice`, `--language`, `--format`, `--speed`, and `--output`.",
499
499
  "Use the `tts.synthesize` action when the user asks to generate spoken audio or a reusable audio file tag.",
500
500
  "A successful synthesis returns a local output path and a reusable `<file type=\"audio\">...</file>` tag for downstream sending.",
501
501
  "If the Python runner prints non-fatal stderr, the command still succeeds and returns that stderr summary as extra context.",
502
- "Example: `studio tts synthesize \"你好,欢迎来到 Downcity\" --format wav`",
502
+ "Example: `town tts synthesize \"你好,欢迎来到 Downcity\" --format wav`",
503
503
  ].join("\n");
504
504
  },
505
505
  };
@@ -2,7 +2,7 @@
2
2
  * TTS 依赖安装器。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一管理 `studio tts` 的 Python 依赖安装逻辑。
5
+ * - 统一管理 `town tts` 的 Python 依赖安装逻辑。
6
6
  * - 根据模型自动推导 runner(qwen3 / kokoro)并执行 `python -m pip install`。
7
7
  */
8
8
 
@@ -2,7 +2,7 @@
2
2
  * Voice 转写依赖安装器。
3
3
  *
4
4
  * 关键点(中文)
5
- * - 统一管理 `studio voice` 的 Python 依赖安装逻辑。
5
+ * - 统一管理 `town voice` 的 Python 依赖安装逻辑。
6
6
  * - 根据模型自动推导 runner(funasr / transformers-whisper)并执行 `python -m pip install`。
7
7
  * - 返回结构化安装结果,供 CLI/日志/测试复用。
8
8
  */
@@ -292,7 +292,7 @@ async function resolveVoiceConfig(input: VoiceTranscribeInput): Promise<VoiceCon
292
292
  const enabled =
293
293
  pluginConfig && (pluginConfig as { enabled?: unknown }).enabled === true;
294
294
  if (!enabled) {
295
- throw new Error("ASR plugin is disabled. Run `studio asr on` first.");
295
+ throw new Error("ASR plugin is disabled. Run `town asr on` first.");
296
296
  }
297
297
 
298
298
  const provider = String(
@@ -307,7 +307,7 @@ async function resolveVoiceConfig(input: VoiceTranscribeInput): Promise<VoiceCon
307
307
  (pluginConfig as { modelId?: unknown } | null)?.modelId || "SenseVoiceSmall",
308
308
  ).trim() || "SenseVoiceSmall";
309
309
  if (!modelId && provider === "local") {
310
- throw new Error("ASR active model is not configured. Run `studio asr use <modelId>`.");
310
+ throw new Error("ASR active model is not configured. Run `town asr use <modelId>`.");
311
311
  }
312
312
 
313
313
  const modelsRootDir = resolveVoiceModelsRootDir({
package/tsconfig.json CHANGED
@@ -4,6 +4,7 @@
4
4
  "module": "NodeNext",
5
5
  "moduleResolution": "NodeNext",
6
6
  "lib": ["ES2022"],
7
+ "types": ["node"],
7
8
  "outDir": "./bin",
8
9
  "rootDir": "src",
9
10
  "paths": {