@poping/yome 0.0.2 → 0.0.4

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 (276) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +11 -0
  3. package/README.md +306 -27
  4. package/README.zh-CN.md +333 -0
  5. package/bin/yome-calwatch +0 -0
  6. package/dist/agent.d.ts +24 -2
  7. package/dist/agent.js +34 -2
  8. package/dist/agent.js.map +1 -1
  9. package/dist/context.d.ts +2 -0
  10. package/dist/context.js +121 -13
  11. package/dist/context.js.map +1 -1
  12. package/dist/daemon/calendarPermission.d.ts +10 -0
  13. package/dist/daemon/calendarPermission.js +68 -0
  14. package/dist/daemon/calendarPermission.js.map +1 -0
  15. package/dist/daemon/cronCli.d.ts +19 -0
  16. package/dist/daemon/cronCli.js +403 -0
  17. package/dist/daemon/cronCli.js.map +1 -0
  18. package/dist/daemon/envHint.d.ts +5 -0
  19. package/dist/daemon/envHint.js +139 -0
  20. package/dist/daemon/envHint.js.map +1 -0
  21. package/dist/daemon/humanCron.d.ts +1 -0
  22. package/dist/daemon/humanCron.js +72 -0
  23. package/dist/daemon/humanCron.js.map +1 -0
  24. package/dist/daemon/humanOnce.d.ts +1 -0
  25. package/dist/daemon/humanOnce.js +54 -0
  26. package/dist/daemon/humanOnce.js.map +1 -0
  27. package/dist/daemon/index.d.ts +5 -0
  28. package/dist/daemon/index.js +168 -0
  29. package/dist/daemon/index.js.map +1 -0
  30. package/dist/daemon/launchd.d.ts +7 -0
  31. package/dist/daemon/launchd.js +93 -0
  32. package/dist/daemon/launchd.js.map +1 -0
  33. package/dist/daemon/log.d.ts +17 -0
  34. package/dist/daemon/log.js +57 -0
  35. package/dist/daemon/log.js.map +1 -0
  36. package/dist/daemon/paths.d.ts +11 -0
  37. package/dist/daemon/paths.js +27 -0
  38. package/dist/daemon/paths.js.map +1 -0
  39. package/dist/daemon/runTaskEntry.d.ts +1 -0
  40. package/dist/daemon/runTaskEntry.js +67 -0
  41. package/dist/daemon/runTaskEntry.js.map +1 -0
  42. package/dist/daemon/runner.d.ts +21 -0
  43. package/dist/daemon/runner.js +175 -0
  44. package/dist/daemon/runner.js.map +1 -0
  45. package/dist/daemon/scheduler.d.ts +5 -0
  46. package/dist/daemon/scheduler.js +162 -0
  47. package/dist/daemon/scheduler.js.map +1 -0
  48. package/dist/daemon/taskStore.d.ts +62 -0
  49. package/dist/daemon/taskStore.js +88 -0
  50. package/dist/daemon/taskStore.js.map +1 -0
  51. package/dist/daemon/triggers/calendar.d.ts +8 -0
  52. package/dist/daemon/triggers/calendar.js +248 -0
  53. package/dist/daemon/triggers/calendar.js.map +1 -0
  54. package/dist/daemon/triggers/childRunner.d.ts +14 -0
  55. package/dist/daemon/triggers/childRunner.js +111 -0
  56. package/dist/daemon/triggers/childRunner.js.map +1 -0
  57. package/dist/daemon/triggers/cron.d.ts +14 -0
  58. package/dist/daemon/triggers/cron.js +91 -0
  59. package/dist/daemon/triggers/cron.js.map +1 -0
  60. package/dist/daemon/triggers/file.d.ts +7 -0
  61. package/dist/daemon/triggers/file.js +123 -0
  62. package/dist/daemon/triggers/file.js.map +1 -0
  63. package/dist/daemon/triggers/once.d.ts +10 -0
  64. package/dist/daemon/triggers/once.js +80 -0
  65. package/dist/daemon/triggers/once.js.map +1 -0
  66. package/dist/index.js +240 -15
  67. package/dist/index.js.map +1 -1
  68. package/dist/llm.js +45 -2
  69. package/dist/llm.js.map +1 -1
  70. package/dist/loops/chain.js +8 -0
  71. package/dist/loops/chain.js.map +1 -1
  72. package/dist/loops/evaluator.js +8 -0
  73. package/dist/loops/evaluator.js.map +1 -1
  74. package/dist/loops/orchestrator.js +8 -0
  75. package/dist/loops/orchestrator.js.map +1 -1
  76. package/dist/loops/parallel.js.map +1 -1
  77. package/dist/loops/route.js +8 -0
  78. package/dist/loops/route.js.map +1 -1
  79. package/dist/loops/simple.js +15 -0
  80. package/dist/loops/simple.js.map +1 -1
  81. package/dist/permissions/index.d.ts +1 -1
  82. package/dist/permissions/index.js +1 -1
  83. package/dist/permissions/index.js.map +1 -1
  84. package/dist/permissions/loader.d.ts +20 -1
  85. package/dist/permissions/loader.js +51 -0
  86. package/dist/permissions/loader.js.map +1 -1
  87. package/dist/redact.d.ts +56 -0
  88. package/dist/redact.js +191 -0
  89. package/dist/redact.js.map +1 -0
  90. package/dist/skills/runner/applescript.d.ts +49 -0
  91. package/dist/skills/runner/applescript.js +100 -0
  92. package/dist/skills/runner/applescript.js.map +1 -0
  93. package/dist/skills/runner/dispatcher.d.ts +128 -0
  94. package/dist/skills/runner/dispatcher.js +617 -0
  95. package/dist/skills/runner/dispatcher.js.map +1 -0
  96. package/dist/skills/runner/dispatcher.test.d.ts +1 -0
  97. package/dist/skills/runner/dispatcher.test.js +141 -0
  98. package/dist/skills/runner/dispatcher.test.js.map +1 -0
  99. package/dist/skills/runner/kernel.d.ts +8 -0
  100. package/dist/skills/runner/kernel.js +731 -0
  101. package/dist/skills/runner/kernel.js.map +1 -0
  102. package/dist/skills/runner/nodeBackend.d.ts +32 -0
  103. package/dist/skills/runner/nodeBackend.js +147 -0
  104. package/dist/skills/runner/nodeBackend.js.map +1 -0
  105. package/dist/skills/runner/tokenizer.d.ts +36 -0
  106. package/dist/skills/runner/tokenizer.js +177 -0
  107. package/dist/skills/runner/tokenizer.js.map +1 -0
  108. package/dist/state/todos.d.ts +12 -0
  109. package/dist/state/todos.js +32 -0
  110. package/dist/state/todos.js.map +1 -0
  111. package/dist/threadCli.d.ts +11 -0
  112. package/dist/threadCli.js +177 -0
  113. package/dist/threadCli.js.map +1 -0
  114. package/dist/threadShare.d.ts +21 -0
  115. package/dist/threadShare.js +121 -0
  116. package/dist/threadShare.js.map +1 -0
  117. package/dist/threadSubmit.d.ts +32 -0
  118. package/dist/threadSubmit.js +199 -0
  119. package/dist/threadSubmit.js.map +1 -0
  120. package/dist/tools/askUser.d.ts +20 -0
  121. package/dist/tools/askUser.js +126 -0
  122. package/dist/tools/askUser.js.map +1 -0
  123. package/dist/tools/bash.js +63 -14
  124. package/dist/tools/bash.js.map +1 -1
  125. package/dist/tools/index.d.ts +24 -2
  126. package/dist/tools/index.js +54 -5
  127. package/dist/tools/index.js.map +1 -1
  128. package/dist/tools/skillCall.d.ts +2 -0
  129. package/dist/tools/skillCall.js +77 -0
  130. package/dist/tools/skillCall.js.map +1 -0
  131. package/dist/tools/todoWrite.d.ts +2 -0
  132. package/dist/tools/todoWrite.js +141 -0
  133. package/dist/tools/todoWrite.js.map +1 -0
  134. package/dist/tools/yome.d.ts +2 -0
  135. package/dist/tools/yome.js +87 -0
  136. package/dist/tools/yome.js.map +1 -0
  137. package/dist/ui/AgentPicker.js +3 -3
  138. package/dist/ui/AgentPicker.js.map +1 -1
  139. package/dist/ui/App.js +263 -61
  140. package/dist/ui/App.js.map +1 -1
  141. package/dist/ui/AskUserPrompt.d.ts +7 -0
  142. package/dist/ui/AskUserPrompt.js +78 -0
  143. package/dist/ui/AskUserPrompt.js.map +1 -0
  144. package/dist/ui/Banner.d.ts +2 -1
  145. package/dist/ui/Banner.js +23 -4
  146. package/dist/ui/Banner.js.map +1 -1
  147. package/dist/ui/InputBar.js +25 -36
  148. package/dist/ui/InputBar.js.map +1 -1
  149. package/dist/ui/Markdown.d.ts +2 -2
  150. package/dist/ui/Markdown.js +22 -7
  151. package/dist/ui/Markdown.js.map +1 -1
  152. package/dist/ui/MarketplacePicker.d.ts +7 -0
  153. package/dist/ui/MarketplacePicker.js +122 -0
  154. package/dist/ui/MarketplacePicker.js.map +1 -0
  155. package/dist/ui/MessageList.d.ts +12 -1
  156. package/dist/ui/MessageList.js +72 -7
  157. package/dist/ui/MessageList.js.map +1 -1
  158. package/dist/ui/ModelPicker.js +4 -4
  159. package/dist/ui/ModelPicker.js.map +1 -1
  160. package/dist/ui/MultilineTextInput.d.ts +31 -0
  161. package/dist/ui/MultilineTextInput.js +393 -0
  162. package/dist/ui/MultilineTextInput.js.map +1 -0
  163. package/dist/ui/MultilineTextInput.test.d.ts +1 -0
  164. package/dist/ui/MultilineTextInput.test.js +30 -0
  165. package/dist/ui/MultilineTextInput.test.js.map +1 -0
  166. package/dist/ui/PermissionPrompt.d.ts +16 -4
  167. package/dist/ui/PermissionPrompt.js +60 -15
  168. package/dist/ui/PermissionPrompt.js.map +1 -1
  169. package/dist/ui/SessionPicker.js +2 -2
  170. package/dist/ui/SessionPicker.js.map +1 -1
  171. package/dist/ui/ShimmerText.d.ts +8 -0
  172. package/dist/ui/ShimmerText.js +40 -0
  173. package/dist/ui/ShimmerText.js.map +1 -0
  174. package/dist/ui/Spinner.js +3 -9
  175. package/dist/ui/Spinner.js.map +1 -1
  176. package/dist/ui/TodoPanel.d.ts +7 -0
  177. package/dist/ui/TodoPanel.js +36 -0
  178. package/dist/ui/TodoPanel.js.map +1 -0
  179. package/dist/ui/TogglePicker.js +4 -4
  180. package/dist/ui/TogglePicker.js.map +1 -1
  181. package/dist/ui/ToolResult.js +6 -0
  182. package/dist/ui/ToolResult.js.map +1 -1
  183. package/dist/ui/UnifiedSkillsPicker.d.ts +10 -0
  184. package/dist/ui/UnifiedSkillsPicker.js +63 -0
  185. package/dist/ui/UnifiedSkillsPicker.js.map +1 -0
  186. package/dist/ui/animation.d.ts +3 -0
  187. package/dist/ui/animation.js +48 -0
  188. package/dist/ui/animation.js.map +1 -0
  189. package/dist/ui/useThrottledStream.d.ts +7 -0
  190. package/dist/ui/useThrottledStream.js +63 -0
  191. package/dist/ui/useThrottledStream.js.map +1 -0
  192. package/dist/yomeSkills/auth.d.ts +20 -0
  193. package/dist/yomeSkills/auth.js +70 -0
  194. package/dist/yomeSkills/auth.js.map +1 -0
  195. package/dist/yomeSkills/blacklist.d.ts +33 -0
  196. package/dist/yomeSkills/blacklist.js +101 -0
  197. package/dist/yomeSkills/blacklist.js.map +1 -0
  198. package/dist/yomeSkills/capabilities.d.ts +54 -0
  199. package/dist/yomeSkills/capabilities.js +175 -0
  200. package/dist/yomeSkills/capabilities.js.map +1 -0
  201. package/dist/yomeSkills/capabilityGuard.d.ts +31 -0
  202. package/dist/yomeSkills/capabilityGuard.js +113 -0
  203. package/dist/yomeSkills/capabilityGuard.js.map +1 -0
  204. package/dist/yomeSkills/cli.d.ts +25 -0
  205. package/dist/yomeSkills/cli.js +624 -0
  206. package/dist/yomeSkills/cli.js.map +1 -0
  207. package/dist/yomeSkills/deprecate.d.ts +29 -0
  208. package/dist/yomeSkills/deprecate.js +99 -0
  209. package/dist/yomeSkills/deprecate.js.map +1 -0
  210. package/dist/yomeSkills/devLink.d.ts +17 -0
  211. package/dist/yomeSkills/devLink.js +91 -0
  212. package/dist/yomeSkills/devLink.js.map +1 -0
  213. package/dist/yomeSkills/doctor.d.ts +13 -0
  214. package/dist/yomeSkills/doctor.js +152 -0
  215. package/dist/yomeSkills/doctor.js.map +1 -0
  216. package/dist/yomeSkills/enable.d.ts +8 -0
  217. package/dist/yomeSkills/enable.js +67 -0
  218. package/dist/yomeSkills/enable.js.map +1 -0
  219. package/dist/yomeSkills/hubPing.d.ts +1 -0
  220. package/dist/yomeSkills/hubPing.js +41 -0
  221. package/dist/yomeSkills/hubPing.js.map +1 -0
  222. package/dist/yomeSkills/install.d.ts +18 -0
  223. package/dist/yomeSkills/install.js +143 -0
  224. package/dist/yomeSkills/install.js.map +1 -0
  225. package/dist/yomeSkills/installFromHubTarball.d.ts +26 -0
  226. package/dist/yomeSkills/installFromHubTarball.js +161 -0
  227. package/dist/yomeSkills/installFromHubTarball.js.map +1 -0
  228. package/dist/yomeSkills/installGithub.d.ts +33 -0
  229. package/dist/yomeSkills/installGithub.js +213 -0
  230. package/dist/yomeSkills/installGithub.js.map +1 -0
  231. package/dist/yomeSkills/installMeta.d.ts +8 -0
  232. package/dist/yomeSkills/installMeta.js +76 -0
  233. package/dist/yomeSkills/installMeta.js.map +1 -0
  234. package/dist/yomeSkills/integrity.d.ts +26 -0
  235. package/dist/yomeSkills/integrity.js +107 -0
  236. package/dist/yomeSkills/integrity.js.map +1 -0
  237. package/dist/yomeSkills/invoke.d.ts +29 -0
  238. package/dist/yomeSkills/invoke.js +135 -0
  239. package/dist/yomeSkills/invoke.js.map +1 -0
  240. package/dist/yomeSkills/list.d.ts +11 -0
  241. package/dist/yomeSkills/list.js +55 -0
  242. package/dist/yomeSkills/list.js.map +1 -0
  243. package/dist/yomeSkills/login.d.ts +41 -0
  244. package/dist/yomeSkills/login.js +221 -0
  245. package/dist/yomeSkills/login.js.map +1 -0
  246. package/dist/yomeSkills/manifest.d.ts +60 -0
  247. package/dist/yomeSkills/manifest.js +47 -0
  248. package/dist/yomeSkills/manifest.js.map +1 -0
  249. package/dist/yomeSkills/paths.d.ts +13 -0
  250. package/dist/yomeSkills/paths.js +33 -0
  251. package/dist/yomeSkills/paths.js.map +1 -0
  252. package/dist/yomeSkills/publish.d.ts +18 -0
  253. package/dist/yomeSkills/publish.js +114 -0
  254. package/dist/yomeSkills/publish.js.map +1 -0
  255. package/dist/yomeSkills/rollback.d.ts +10 -0
  256. package/dist/yomeSkills/rollback.js +83 -0
  257. package/dist/yomeSkills/rollback.js.map +1 -0
  258. package/dist/yomeSkills/search.d.ts +21 -0
  259. package/dist/yomeSkills/search.js +31 -0
  260. package/dist/yomeSkills/search.js.map +1 -0
  261. package/dist/yomeSkills/skillsIndex.d.ts +36 -0
  262. package/dist/yomeSkills/skillsIndex.js +111 -0
  263. package/dist/yomeSkills/skillsIndex.js.map +1 -0
  264. package/dist/yomeSkills/unified.d.ts +53 -0
  265. package/dist/yomeSkills/unified.js +187 -0
  266. package/dist/yomeSkills/unified.js.map +1 -0
  267. package/dist/yomeSkills/uninstall.d.ts +7 -0
  268. package/dist/yomeSkills/uninstall.js +22 -0
  269. package/dist/yomeSkills/uninstall.js.map +1 -0
  270. package/dist/yomeSkills/update.d.ts +18 -0
  271. package/dist/yomeSkills/update.js +75 -0
  272. package/dist/yomeSkills/update.js.map +1 -0
  273. package/dist/yomeSkills/validate.d.ts +11 -0
  274. package/dist/yomeSkills/validate.js +99 -0
  275. package/dist/yomeSkills/validate.js.map +1 -0
  276. package/package.json +23 -6
@@ -0,0 +1,21 @@
1
+ import type { YomeConfig } from '../config.js';
2
+ export interface DaemonTaskSpec {
3
+ taskId: string;
4
+ prompt: string;
5
+ cwd?: string;
6
+ /** Permission allowlist, e.g. ['Read', 'Write', 'Yome(@yome/fs:*)']. */
7
+ autoAllow?: string[];
8
+ /** Permission denylist (overrides allowlist), e.g. ['Bash(rm:*)']. */
9
+ autoDeny?: string[];
10
+ }
11
+ export interface DaemonTaskResult {
12
+ ok: boolean;
13
+ finalText: string;
14
+ toolCalls: number;
15
+ inputTokens: number;
16
+ outputTokens: number;
17
+ durationMs: number;
18
+ logFile: string;
19
+ error?: string;
20
+ }
21
+ export declare function runDaemonTask(config: YomeConfig, spec: DaemonTaskSpec): Promise<DaemonTaskResult>;
@@ -0,0 +1,175 @@
1
+ // Daemon-side Agent runner — "non-interactive" mode.
2
+ //
3
+ // Reuses cli/src/agent.ts wholesale. The trick is in WHICH callbacks we
4
+ // register:
5
+ // - onAskPermission → auto-deny (with feedback to the LLM) instead of
6
+ // prompting a human
7
+ // - setAskUserHandler is NOT called → AskUser tool short-circuits per
8
+ // its own headless contract (see tools/askUser.ts)
9
+ // - autoAllow / autoDeny rules layered into the permission context
10
+ // - all tool_use / tool_result / text_delta written to a per-run jsonl
11
+ // audit log
12
+ //
13
+ // The agent's own MAX_ITERATIONS=30 (loops/simple.ts) is the iteration
14
+ // safety net. Wall-time budget is enforced by the parent process spawning
15
+ // the runner with a kill timer (see triggers/cron.ts).
16
+ import { Agent } from '../agent.js';
17
+ import { appendLog, openTaskLog } from './log.js';
18
+ /**
19
+ * Default safety denylist applied to every daemon task on top of the
20
+ * user's autoDeny.
21
+ *
22
+ * We deliberately keep this list TINY. Daemon tasks already require an
23
+ * explicit `--allow Bash(*)` to use Bash at all, so a second layer of
24
+ * "no rm, no chmod" was over-cautious and broke common scripted
25
+ * workflows (Agent writes a shell script then can't `chmod +x` it,
26
+ * Agent does `rm /tmp/somefile` and gets blocked, etc.).
27
+ *
28
+ * We only block the patterns that are catastrophic and cannot be
29
+ * undone: `sudo` (privilege escalation), and `rm -rf` against root or
30
+ * the user's home. Garden-variety `rm somefile` is allowed; if you don't
31
+ * want the agent deleting files at all, use `--deny "Bash(rm:*)"` per
32
+ * task.
33
+ */
34
+ const DEFAULT_DAEMON_DENY = [
35
+ 'Bash(sudo:*)',
36
+ 'Bash(rm -rf /:*)',
37
+ 'Bash(rm -rf /*:*)',
38
+ 'Bash(rm -rf ~:*)',
39
+ 'Bash(rm -rf ~/:*)',
40
+ 'Bash(rm -rf $HOME:*)',
41
+ 'Bash(rm -rf $HOME/:*)',
42
+ ];
43
+ export async function runDaemonTask(config, spec) {
44
+ const runTs = Date.now();
45
+ const logFile = openTaskLog(spec.taskId, runTs);
46
+ appendLog(logFile, {
47
+ type: 'run_start',
48
+ taskId: spec.taskId,
49
+ prompt: spec.prompt,
50
+ autoAllow: spec.autoAllow ?? [],
51
+ autoDeny: spec.autoDeny ?? [],
52
+ cwd: spec.cwd ?? process.cwd(),
53
+ model: config.model,
54
+ });
55
+ // Optional cwd switch — many tasks expect to read/write under a specific
56
+ // directory, but we don't want to pollute the daemon's own cwd.
57
+ const originalCwd = process.cwd();
58
+ if (spec.cwd) {
59
+ try {
60
+ process.chdir(spec.cwd);
61
+ }
62
+ catch (e) {
63
+ appendLog(logFile, { type: 'error', stage: 'chdir', message: String(e) });
64
+ }
65
+ }
66
+ const agent = new Agent(config);
67
+ for (const rule of spec.autoAllow ?? []) {
68
+ agent.addPermissionRule(rule, 'allow', 'session');
69
+ }
70
+ for (const rule of [...DEFAULT_DAEMON_DENY, ...(spec.autoDeny ?? [])]) {
71
+ agent.addPermissionRule(rule, 'deny', 'session');
72
+ }
73
+ const onAskPermission = async (toolName, message, input) => {
74
+ appendLog(logFile, {
75
+ type: 'permission_denied_auto',
76
+ toolName,
77
+ message,
78
+ input: redactForLog(input),
79
+ });
80
+ return {
81
+ decision: 'deny',
82
+ feedback: `Daemon mode: '${toolName}' is not in this task's autoAllow list. ` +
83
+ `Either complete the task with a different tool or stop and explain why.`,
84
+ };
85
+ };
86
+ let finalText = '';
87
+ let toolCalls = 0;
88
+ let inputTokens = 0;
89
+ let outputTokens = 0;
90
+ let error;
91
+ try {
92
+ await agent.run(spec.prompt, {
93
+ onTextDelta: (text) => {
94
+ finalText += text;
95
+ // We don't log every delta (too chatty); the run_end entry has the
96
+ // full assembled text.
97
+ },
98
+ onToolUse: (name, input) => {
99
+ toolCalls++;
100
+ appendLog(logFile, { type: 'tool_use', name, input: redactForLog(input) });
101
+ },
102
+ onToolResult: (name, result) => {
103
+ appendLog(logFile, {
104
+ type: 'tool_result',
105
+ name,
106
+ result: result.length > 4_000 ? result.slice(0, 4_000) + '…[truncated]' : result,
107
+ });
108
+ },
109
+ onDone: (usage) => {
110
+ inputTokens = usage.inputTokens;
111
+ outputTokens = usage.outputTokens;
112
+ },
113
+ onError: (err) => {
114
+ error = err?.message ?? String(err);
115
+ appendLog(logFile, { type: 'error', stage: 'agent_loop', message: error });
116
+ },
117
+ onAskPermission,
118
+ });
119
+ }
120
+ catch (e) {
121
+ error = e?.message ?? String(e);
122
+ appendLog(logFile, { type: 'error', stage: 'unhandled', message: error });
123
+ }
124
+ finally {
125
+ if (spec.cwd) {
126
+ try {
127
+ process.chdir(originalCwd);
128
+ }
129
+ catch { /* noop */ }
130
+ }
131
+ }
132
+ const durationMs = Date.now() - runTs;
133
+ const ok = !error;
134
+ appendLog(logFile, {
135
+ type: 'run_end',
136
+ ok,
137
+ durationMs,
138
+ toolCalls,
139
+ inputTokens,
140
+ outputTokens,
141
+ finalText: finalText.length > 4_000 ? finalText.slice(0, 4_000) + '…[truncated]' : finalText,
142
+ error,
143
+ });
144
+ return {
145
+ ok,
146
+ finalText: finalText.trim(),
147
+ toolCalls,
148
+ inputTokens,
149
+ outputTokens,
150
+ durationMs,
151
+ logFile,
152
+ error,
153
+ };
154
+ }
155
+ /**
156
+ * Strip obvious secrets from tool input before writing to disk. The audit
157
+ * log lives in plaintext so we should not leak API keys / tokens that the
158
+ * agent might pass through. Best-effort — not a security boundary.
159
+ */
160
+ function redactForLog(input) {
161
+ const out = {};
162
+ for (const [k, v] of Object.entries(input)) {
163
+ if (/key|token|secret|password|authorization/i.test(k)) {
164
+ out[k] = '[redacted]';
165
+ }
166
+ else if (typeof v === 'string' && v.length > 2_000) {
167
+ out[k] = v.slice(0, 2_000) + '…[truncated]';
168
+ }
169
+ else {
170
+ out[k] = v;
171
+ }
172
+ }
173
+ return out;
174
+ }
175
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/daemon/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { TaskRecord } from './taskStore.js';
2
+ export declare function startDaemon(): void;
3
+ /** Used by `yome daemon status` (called from a separate process — peeks pid file). */
4
+ export declare function readPidIfRunning(): number | null;
5
+ export { TaskRecord };
@@ -0,0 +1,162 @@
1
+ // Daemon main loop.
2
+ //
3
+ // Responsibilities:
4
+ // 1. Read tasks.json on startup, register a node-cron job per
5
+ // enabled cron task.
6
+ // 2. Watch tasks.json for changes (re-register on edit so that
7
+ // `yome cron add/rm/...` takes effect without restarting daemon).
8
+ // 3. Handle SIGTERM/SIGINT cleanly (unregister jobs, remove pid file).
9
+ //
10
+ // File-trigger and calendar-trigger registration is left as TODO hooks
11
+ // (PR2 / PR4). The shape mirrors registerCronTask so adding a new
12
+ // trigger kind is "implement registerXxxTask + branch on kind here".
13
+ import { watch } from 'fs';
14
+ import { writeFileSync, unlinkSync, existsSync, readFileSync } from 'fs';
15
+ import { listTasks } from './taskStore.js';
16
+ import { registerCronTask, unregisterCronTask, listActive as listActiveCron, resolveYomeBinPath } from './triggers/cron.js';
17
+ import { registerOnceTask, unregisterOnceTask, listActiveOnce } from './triggers/once.js';
18
+ import { registerFileTask, unregisterFileTask, listActiveFile } from './triggers/file.js';
19
+ import { registerCalendarTask, unregisterCalendarTask, listActiveCalendar } from './triggers/calendar.js';
20
+ import { ensureDirs, PID_FILE, TASKS_FILE } from './paths.js';
21
+ let started = false;
22
+ let watcher = null;
23
+ let reloadDebounce = null;
24
+ export function startDaemon() {
25
+ if (started)
26
+ return;
27
+ started = true;
28
+ ensureDirs();
29
+ writePidFile();
30
+ installSignalHandlers();
31
+ reloadAllTasks();
32
+ watchTasksFile();
33
+ // eslint-disable-next-line no-console
34
+ console.log(`[daemon] started (pid=${process.pid}); ` +
35
+ `cron=${listActiveCron().length} once=${listActiveOnce().length} ` +
36
+ `file=${listActiveFile().length} calendar=${listActiveCalendar().length}`);
37
+ }
38
+ function reloadAllTasks() {
39
+ const yomeBinPath = resolveYomeBinPath();
40
+ const tasks = listTasks();
41
+ const seen = new Set();
42
+ for (const t of tasks) {
43
+ seen.add(t.id);
44
+ if (!t.enabled) {
45
+ unregisterAllForId(t.id);
46
+ continue;
47
+ }
48
+ switch (t.trigger.kind) {
49
+ case 'cron':
50
+ registerCronTask(t, { yomeBinPath });
51
+ break;
52
+ case 'once':
53
+ registerOnceTask(t, { yomeBinPath });
54
+ break;
55
+ case 'file':
56
+ registerFileTask(t, { yomeBinPath });
57
+ break;
58
+ case 'calendar':
59
+ registerCalendarTask(t, { yomeBinPath });
60
+ break;
61
+ }
62
+ }
63
+ // Drop any active registrations that no longer exist in tasks.json.
64
+ for (const activeId of [
65
+ ...listActiveCron(),
66
+ ...listActiveOnce().map((o) => o.taskId),
67
+ ...listActiveFile(),
68
+ ...listActiveCalendar(),
69
+ ]) {
70
+ if (!seen.has(activeId))
71
+ unregisterAllForId(activeId);
72
+ }
73
+ }
74
+ /** Idempotently unregister an id from every trigger subsystem. */
75
+ function unregisterAllForId(id) {
76
+ unregisterCronTask(id);
77
+ unregisterOnceTask(id);
78
+ unregisterFileTask(id);
79
+ unregisterCalendarTask(id);
80
+ }
81
+ function watchTasksFile() {
82
+ // tasks.json is written via tmp+rename (atomic). fs.watch on the file
83
+ // itself loses its handle after the first rename — the kernel inode
84
+ // changes out from under it. Watching the PARENT directory and
85
+ // filtering for tasks.json events survives renames forever and works
86
+ // on macOS, Linux, and Windows.
87
+ const dir = TASKS_FILE.replace(/\/[^/]+$/, '');
88
+ const fileBase = TASKS_FILE.split('/').pop();
89
+ try {
90
+ watcher = watch(dir, (_eventType, filename) => {
91
+ if (filename !== fileBase && filename !== `${fileBase}.tmp`)
92
+ return;
93
+ if (reloadDebounce)
94
+ clearTimeout(reloadDebounce);
95
+ reloadDebounce = setTimeout(() => {
96
+ if (!existsSync(TASKS_FILE))
97
+ return; // mid-rename window
98
+ // eslint-disable-next-line no-console
99
+ console.log('[daemon] tasks.json changed, reloading…');
100
+ try {
101
+ reloadAllTasks();
102
+ }
103
+ catch (e) {
104
+ console.error('[daemon] reload failed:', e);
105
+ }
106
+ }, 250);
107
+ });
108
+ }
109
+ catch (e) {
110
+ console.error('[daemon] failed to watch tasks dir:', e);
111
+ }
112
+ }
113
+ function writePidFile() {
114
+ try {
115
+ writeFileSync(PID_FILE, String(process.pid), 'utf-8');
116
+ }
117
+ catch { /* noop */ }
118
+ }
119
+ function removePidFile() {
120
+ try {
121
+ unlinkSync(PID_FILE);
122
+ }
123
+ catch { /* noop */ }
124
+ }
125
+ function installSignalHandlers() {
126
+ const shutdown = (sig) => {
127
+ // eslint-disable-next-line no-console
128
+ console.log(`[daemon] received ${sig}, shutting down…`);
129
+ if (watcher)
130
+ try {
131
+ watcher.close();
132
+ }
133
+ catch { /* noop */ }
134
+ removePidFile();
135
+ process.exit(0);
136
+ };
137
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
138
+ process.on('SIGINT', () => shutdown('SIGINT'));
139
+ }
140
+ /** Used by `yome daemon status` (called from a separate process — peeks pid file). */
141
+ export function readPidIfRunning() {
142
+ try {
143
+ if (!existsSync(PID_FILE))
144
+ return null;
145
+ const raw = readFileSync(PID_FILE, 'utf-8').trim();
146
+ const pid = Number.parseInt(raw, 10);
147
+ if (!pid || Number.isNaN(pid))
148
+ return null;
149
+ // process.kill(pid, 0) throws if the process doesn't exist.
150
+ try {
151
+ process.kill(pid, 0);
152
+ return pid;
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
158
+ catch {
159
+ return null;
160
+ }
161
+ }
162
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/daemon/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ export type CalendarEventKind = 'event-start' | 'event-end' | 'event-added';
2
+ export type TriggerSpec = {
3
+ kind: 'cron';
4
+ schedule: string;
5
+ tz?: string;
6
+ } | {
7
+ kind: 'once';
8
+ atMs: number;
9
+ } | {
10
+ kind: 'file';
11
+ path: string;
12
+ events?: ('change' | 'add' | 'unlink')[];
13
+ } | {
14
+ kind: 'calendar';
15
+ events: CalendarEventKind[];
16
+ /** For event-start: fire this many ms BEFORE the event begins. Default 0. */
17
+ leadMs?: number;
18
+ /** Optional case-insensitive regex on event title. */
19
+ titleRegex?: string;
20
+ /** Optional case-insensitive substring of calendar display name. */
21
+ calendar?: string;
22
+ };
23
+ export interface RunSummary {
24
+ ts: number;
25
+ ok: boolean;
26
+ durationMs: number;
27
+ toolCalls: number;
28
+ inputTokens: number;
29
+ outputTokens: number;
30
+ error?: string;
31
+ }
32
+ export interface TaskRecord {
33
+ id: string;
34
+ createdAt: number;
35
+ trigger: TriggerSpec;
36
+ prompt: string;
37
+ cwd?: string;
38
+ /** Permission allow rules layered onto the agent for this task. */
39
+ autoAllow?: string[];
40
+ /** Permission deny rules — override allow. */
41
+ autoDeny?: string[];
42
+ /** Hard wall-time budget. Default 5 min in runner.ts. */
43
+ maxDurationMs?: number;
44
+ /** Extra environment variables passed to the spawned __run-task child.
45
+ * Useful for skill-level switches (e.g. YOME_WEB_HEADLESS=0 to open a
46
+ * visible browser window) without polluting the daemon's own env. */
47
+ env?: Record<string, string>;
48
+ enabled: boolean;
49
+ lastRun?: RunSummary;
50
+ /** Last N run summaries (newest first). Bounded to avoid unbounded growth. */
51
+ history?: RunSummary[];
52
+ /** Free-form description shown in `yome cron list`. */
53
+ note?: string;
54
+ }
55
+ export declare function listTasks(): TaskRecord[];
56
+ export declare function getTask(id: string): TaskRecord | undefined;
57
+ export declare function addTask(input: Omit<TaskRecord, 'id' | 'createdAt' | 'enabled'> & {
58
+ enabled?: boolean;
59
+ }): TaskRecord;
60
+ export declare function removeTask(id: string): boolean;
61
+ export declare function setEnabled(id: string, enabled: boolean): boolean;
62
+ export declare function recordRun(id: string, summary: RunSummary): void;
@@ -0,0 +1,88 @@
1
+ // Persistent task registry for `yome cron`.
2
+ //
3
+ // File: ~/.yome/cron/tasks.json
4
+ // Format: { version: 1, tasks: TaskRecord[] }
5
+ //
6
+ // We keep the schema flat-ish and forward-compatible: extra fields are
7
+ // preserved on round-trip, so future PRs can add (e.g.) calendar / file
8
+ // triggers without breaking older daemon binaries.
9
+ import { readFileSync, writeFileSync, existsSync, renameSync } from 'fs';
10
+ import { randomUUID } from 'crypto';
11
+ import { TASKS_FILE, ensureDirs } from './paths.js';
12
+ const HISTORY_LIMIT = 20;
13
+ function readRaw() {
14
+ if (!existsSync(TASKS_FILE))
15
+ return { version: 1, tasks: [] };
16
+ try {
17
+ const raw = readFileSync(TASKS_FILE, 'utf-8').trim();
18
+ if (!raw)
19
+ return { version: 1, tasks: [] };
20
+ const parsed = JSON.parse(raw);
21
+ if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.tasks)) {
22
+ return { version: 1, tasks: [] };
23
+ }
24
+ return { version: 1, tasks: parsed.tasks };
25
+ }
26
+ catch {
27
+ return { version: 1, tasks: [] };
28
+ }
29
+ }
30
+ function writeRaw(store) {
31
+ ensureDirs();
32
+ // Atomic-ish write via rename to avoid corrupting the file if the
33
+ // daemon dies mid-write (OS will only see the old or the new bytes).
34
+ const tmp = TASKS_FILE + '.tmp';
35
+ writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');
36
+ renameSync(tmp, TASKS_FILE);
37
+ }
38
+ export function listTasks() {
39
+ return readRaw().tasks;
40
+ }
41
+ export function getTask(id) {
42
+ return readRaw().tasks.find((t) => t.id === id);
43
+ }
44
+ export function addTask(input) {
45
+ const store = readRaw();
46
+ const t = {
47
+ id: shortId(),
48
+ createdAt: Date.now(),
49
+ enabled: input.enabled ?? true,
50
+ ...input,
51
+ };
52
+ store.tasks.push(t);
53
+ writeRaw(store);
54
+ return t;
55
+ }
56
+ export function removeTask(id) {
57
+ const store = readRaw();
58
+ const before = store.tasks.length;
59
+ store.tasks = store.tasks.filter((t) => t.id !== id);
60
+ if (store.tasks.length === before)
61
+ return false;
62
+ writeRaw(store);
63
+ return true;
64
+ }
65
+ export function setEnabled(id, enabled) {
66
+ const store = readRaw();
67
+ const t = store.tasks.find((x) => x.id === id);
68
+ if (!t)
69
+ return false;
70
+ t.enabled = enabled;
71
+ writeRaw(store);
72
+ return true;
73
+ }
74
+ export function recordRun(id, summary) {
75
+ const store = readRaw();
76
+ const t = store.tasks.find((x) => x.id === id);
77
+ if (!t)
78
+ return;
79
+ t.lastRun = summary;
80
+ t.history = [summary, ...(t.history ?? [])].slice(0, HISTORY_LIMIT);
81
+ writeRaw(store);
82
+ }
83
+ /** Short, sortable-ish task id: tsk_<8 hex chars>. */
84
+ function shortId() {
85
+ const u = randomUUID().replace(/-/g, '');
86
+ return `tsk_${u.slice(0, 10)}`;
87
+ }
88
+ //# sourceMappingURL=taskStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taskStore.js","sourceRoot":"","sources":["../../src/daemon/taskStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { TaskRecord } from '../taskStore.js';
2
+ interface TriggerCtx {
3
+ yomeBinPath: string;
4
+ }
5
+ export declare function registerCalendarTask(task: TaskRecord, ctx: TriggerCtx): void;
6
+ export declare function unregisterCalendarTask(taskId: string): void;
7
+ export declare function listActiveCalendar(): string[];
8
+ export {};