@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.
- package/LICENSE +202 -0
- package/NOTICE +11 -0
- package/README.md +306 -27
- package/README.zh-CN.md +333 -0
- package/bin/yome-calwatch +0 -0
- package/dist/agent.d.ts +24 -2
- package/dist/agent.js +34 -2
- package/dist/agent.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.js +121 -13
- package/dist/context.js.map +1 -1
- package/dist/daemon/calendarPermission.d.ts +10 -0
- package/dist/daemon/calendarPermission.js +68 -0
- package/dist/daemon/calendarPermission.js.map +1 -0
- package/dist/daemon/cronCli.d.ts +19 -0
- package/dist/daemon/cronCli.js +403 -0
- package/dist/daemon/cronCli.js.map +1 -0
- package/dist/daemon/envHint.d.ts +5 -0
- package/dist/daemon/envHint.js +139 -0
- package/dist/daemon/envHint.js.map +1 -0
- package/dist/daemon/humanCron.d.ts +1 -0
- package/dist/daemon/humanCron.js +72 -0
- package/dist/daemon/humanCron.js.map +1 -0
- package/dist/daemon/humanOnce.d.ts +1 -0
- package/dist/daemon/humanOnce.js +54 -0
- package/dist/daemon/humanOnce.js.map +1 -0
- package/dist/daemon/index.d.ts +5 -0
- package/dist/daemon/index.js +168 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/launchd.d.ts +7 -0
- package/dist/daemon/launchd.js +93 -0
- package/dist/daemon/launchd.js.map +1 -0
- package/dist/daemon/log.d.ts +17 -0
- package/dist/daemon/log.js +57 -0
- package/dist/daemon/log.js.map +1 -0
- package/dist/daemon/paths.d.ts +11 -0
- package/dist/daemon/paths.js +27 -0
- package/dist/daemon/paths.js.map +1 -0
- package/dist/daemon/runTaskEntry.d.ts +1 -0
- package/dist/daemon/runTaskEntry.js +67 -0
- package/dist/daemon/runTaskEntry.js.map +1 -0
- package/dist/daemon/runner.d.ts +21 -0
- package/dist/daemon/runner.js +175 -0
- package/dist/daemon/runner.js.map +1 -0
- package/dist/daemon/scheduler.d.ts +5 -0
- package/dist/daemon/scheduler.js +162 -0
- package/dist/daemon/scheduler.js.map +1 -0
- package/dist/daemon/taskStore.d.ts +62 -0
- package/dist/daemon/taskStore.js +88 -0
- package/dist/daemon/taskStore.js.map +1 -0
- package/dist/daemon/triggers/calendar.d.ts +8 -0
- package/dist/daemon/triggers/calendar.js +248 -0
- package/dist/daemon/triggers/calendar.js.map +1 -0
- package/dist/daemon/triggers/childRunner.d.ts +14 -0
- package/dist/daemon/triggers/childRunner.js +111 -0
- package/dist/daemon/triggers/childRunner.js.map +1 -0
- package/dist/daemon/triggers/cron.d.ts +14 -0
- package/dist/daemon/triggers/cron.js +91 -0
- package/dist/daemon/triggers/cron.js.map +1 -0
- package/dist/daemon/triggers/file.d.ts +7 -0
- package/dist/daemon/triggers/file.js +123 -0
- package/dist/daemon/triggers/file.js.map +1 -0
- package/dist/daemon/triggers/once.d.ts +10 -0
- package/dist/daemon/triggers/once.js +80 -0
- package/dist/daemon/triggers/once.js.map +1 -0
- package/dist/index.js +240 -15
- package/dist/index.js.map +1 -1
- package/dist/llm.js +45 -2
- package/dist/llm.js.map +1 -1
- package/dist/loops/chain.js +8 -0
- package/dist/loops/chain.js.map +1 -1
- package/dist/loops/evaluator.js +8 -0
- package/dist/loops/evaluator.js.map +1 -1
- package/dist/loops/orchestrator.js +8 -0
- package/dist/loops/orchestrator.js.map +1 -1
- package/dist/loops/parallel.js.map +1 -1
- package/dist/loops/route.js +8 -0
- package/dist/loops/route.js.map +1 -1
- package/dist/loops/simple.js +15 -0
- package/dist/loops/simple.js.map +1 -1
- package/dist/permissions/index.d.ts +1 -1
- package/dist/permissions/index.js +1 -1
- package/dist/permissions/index.js.map +1 -1
- package/dist/permissions/loader.d.ts +20 -1
- package/dist/permissions/loader.js +51 -0
- package/dist/permissions/loader.js.map +1 -1
- package/dist/redact.d.ts +56 -0
- package/dist/redact.js +191 -0
- package/dist/redact.js.map +1 -0
- package/dist/skills/runner/applescript.d.ts +49 -0
- package/dist/skills/runner/applescript.js +100 -0
- package/dist/skills/runner/applescript.js.map +1 -0
- package/dist/skills/runner/dispatcher.d.ts +128 -0
- package/dist/skills/runner/dispatcher.js +617 -0
- package/dist/skills/runner/dispatcher.js.map +1 -0
- package/dist/skills/runner/dispatcher.test.d.ts +1 -0
- package/dist/skills/runner/dispatcher.test.js +141 -0
- package/dist/skills/runner/dispatcher.test.js.map +1 -0
- package/dist/skills/runner/kernel.d.ts +8 -0
- package/dist/skills/runner/kernel.js +731 -0
- package/dist/skills/runner/kernel.js.map +1 -0
- package/dist/skills/runner/nodeBackend.d.ts +32 -0
- package/dist/skills/runner/nodeBackend.js +147 -0
- package/dist/skills/runner/nodeBackend.js.map +1 -0
- package/dist/skills/runner/tokenizer.d.ts +36 -0
- package/dist/skills/runner/tokenizer.js +177 -0
- package/dist/skills/runner/tokenizer.js.map +1 -0
- package/dist/state/todos.d.ts +12 -0
- package/dist/state/todos.js +32 -0
- package/dist/state/todos.js.map +1 -0
- package/dist/threadCli.d.ts +11 -0
- package/dist/threadCli.js +177 -0
- package/dist/threadCli.js.map +1 -0
- package/dist/threadShare.d.ts +21 -0
- package/dist/threadShare.js +121 -0
- package/dist/threadShare.js.map +1 -0
- package/dist/threadSubmit.d.ts +32 -0
- package/dist/threadSubmit.js +199 -0
- package/dist/threadSubmit.js.map +1 -0
- package/dist/tools/askUser.d.ts +20 -0
- package/dist/tools/askUser.js +126 -0
- package/dist/tools/askUser.js.map +1 -0
- package/dist/tools/bash.js +63 -14
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/index.d.ts +24 -2
- package/dist/tools/index.js +54 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/skillCall.d.ts +2 -0
- package/dist/tools/skillCall.js +77 -0
- package/dist/tools/skillCall.js.map +1 -0
- package/dist/tools/todoWrite.d.ts +2 -0
- package/dist/tools/todoWrite.js +141 -0
- package/dist/tools/todoWrite.js.map +1 -0
- package/dist/tools/yome.d.ts +2 -0
- package/dist/tools/yome.js +87 -0
- package/dist/tools/yome.js.map +1 -0
- package/dist/ui/AgentPicker.js +3 -3
- package/dist/ui/AgentPicker.js.map +1 -1
- package/dist/ui/App.js +263 -61
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/AskUserPrompt.d.ts +7 -0
- package/dist/ui/AskUserPrompt.js +78 -0
- package/dist/ui/AskUserPrompt.js.map +1 -0
- package/dist/ui/Banner.d.ts +2 -1
- package/dist/ui/Banner.js +23 -4
- package/dist/ui/Banner.js.map +1 -1
- package/dist/ui/InputBar.js +25 -36
- package/dist/ui/InputBar.js.map +1 -1
- package/dist/ui/Markdown.d.ts +2 -2
- package/dist/ui/Markdown.js +22 -7
- package/dist/ui/Markdown.js.map +1 -1
- package/dist/ui/MarketplacePicker.d.ts +7 -0
- package/dist/ui/MarketplacePicker.js +122 -0
- package/dist/ui/MarketplacePicker.js.map +1 -0
- package/dist/ui/MessageList.d.ts +12 -1
- package/dist/ui/MessageList.js +72 -7
- package/dist/ui/MessageList.js.map +1 -1
- package/dist/ui/ModelPicker.js +4 -4
- package/dist/ui/ModelPicker.js.map +1 -1
- package/dist/ui/MultilineTextInput.d.ts +31 -0
- package/dist/ui/MultilineTextInput.js +393 -0
- package/dist/ui/MultilineTextInput.js.map +1 -0
- package/dist/ui/MultilineTextInput.test.d.ts +1 -0
- package/dist/ui/MultilineTextInput.test.js +30 -0
- package/dist/ui/MultilineTextInput.test.js.map +1 -0
- package/dist/ui/PermissionPrompt.d.ts +16 -4
- package/dist/ui/PermissionPrompt.js +60 -15
- package/dist/ui/PermissionPrompt.js.map +1 -1
- package/dist/ui/SessionPicker.js +2 -2
- package/dist/ui/SessionPicker.js.map +1 -1
- package/dist/ui/ShimmerText.d.ts +8 -0
- package/dist/ui/ShimmerText.js +40 -0
- package/dist/ui/ShimmerText.js.map +1 -0
- package/dist/ui/Spinner.js +3 -9
- package/dist/ui/Spinner.js.map +1 -1
- package/dist/ui/TodoPanel.d.ts +7 -0
- package/dist/ui/TodoPanel.js +36 -0
- package/dist/ui/TodoPanel.js.map +1 -0
- package/dist/ui/TogglePicker.js +4 -4
- package/dist/ui/TogglePicker.js.map +1 -1
- package/dist/ui/ToolResult.js +6 -0
- package/dist/ui/ToolResult.js.map +1 -1
- package/dist/ui/UnifiedSkillsPicker.d.ts +10 -0
- package/dist/ui/UnifiedSkillsPicker.js +63 -0
- package/dist/ui/UnifiedSkillsPicker.js.map +1 -0
- package/dist/ui/animation.d.ts +3 -0
- package/dist/ui/animation.js +48 -0
- package/dist/ui/animation.js.map +1 -0
- package/dist/ui/useThrottledStream.d.ts +7 -0
- package/dist/ui/useThrottledStream.js +63 -0
- package/dist/ui/useThrottledStream.js.map +1 -0
- package/dist/yomeSkills/auth.d.ts +20 -0
- package/dist/yomeSkills/auth.js +70 -0
- package/dist/yomeSkills/auth.js.map +1 -0
- package/dist/yomeSkills/blacklist.d.ts +33 -0
- package/dist/yomeSkills/blacklist.js +101 -0
- package/dist/yomeSkills/blacklist.js.map +1 -0
- package/dist/yomeSkills/capabilities.d.ts +54 -0
- package/dist/yomeSkills/capabilities.js +175 -0
- package/dist/yomeSkills/capabilities.js.map +1 -0
- package/dist/yomeSkills/capabilityGuard.d.ts +31 -0
- package/dist/yomeSkills/capabilityGuard.js +113 -0
- package/dist/yomeSkills/capabilityGuard.js.map +1 -0
- package/dist/yomeSkills/cli.d.ts +25 -0
- package/dist/yomeSkills/cli.js +624 -0
- package/dist/yomeSkills/cli.js.map +1 -0
- package/dist/yomeSkills/deprecate.d.ts +29 -0
- package/dist/yomeSkills/deprecate.js +99 -0
- package/dist/yomeSkills/deprecate.js.map +1 -0
- package/dist/yomeSkills/devLink.d.ts +17 -0
- package/dist/yomeSkills/devLink.js +91 -0
- package/dist/yomeSkills/devLink.js.map +1 -0
- package/dist/yomeSkills/doctor.d.ts +13 -0
- package/dist/yomeSkills/doctor.js +152 -0
- package/dist/yomeSkills/doctor.js.map +1 -0
- package/dist/yomeSkills/enable.d.ts +8 -0
- package/dist/yomeSkills/enable.js +67 -0
- package/dist/yomeSkills/enable.js.map +1 -0
- package/dist/yomeSkills/hubPing.d.ts +1 -0
- package/dist/yomeSkills/hubPing.js +41 -0
- package/dist/yomeSkills/hubPing.js.map +1 -0
- package/dist/yomeSkills/install.d.ts +18 -0
- package/dist/yomeSkills/install.js +143 -0
- package/dist/yomeSkills/install.js.map +1 -0
- package/dist/yomeSkills/installFromHubTarball.d.ts +26 -0
- package/dist/yomeSkills/installFromHubTarball.js +161 -0
- package/dist/yomeSkills/installFromHubTarball.js.map +1 -0
- package/dist/yomeSkills/installGithub.d.ts +33 -0
- package/dist/yomeSkills/installGithub.js +213 -0
- package/dist/yomeSkills/installGithub.js.map +1 -0
- package/dist/yomeSkills/installMeta.d.ts +8 -0
- package/dist/yomeSkills/installMeta.js +76 -0
- package/dist/yomeSkills/installMeta.js.map +1 -0
- package/dist/yomeSkills/integrity.d.ts +26 -0
- package/dist/yomeSkills/integrity.js +107 -0
- package/dist/yomeSkills/integrity.js.map +1 -0
- package/dist/yomeSkills/invoke.d.ts +29 -0
- package/dist/yomeSkills/invoke.js +135 -0
- package/dist/yomeSkills/invoke.js.map +1 -0
- package/dist/yomeSkills/list.d.ts +11 -0
- package/dist/yomeSkills/list.js +55 -0
- package/dist/yomeSkills/list.js.map +1 -0
- package/dist/yomeSkills/login.d.ts +41 -0
- package/dist/yomeSkills/login.js +221 -0
- package/dist/yomeSkills/login.js.map +1 -0
- package/dist/yomeSkills/manifest.d.ts +60 -0
- package/dist/yomeSkills/manifest.js +47 -0
- package/dist/yomeSkills/manifest.js.map +1 -0
- package/dist/yomeSkills/paths.d.ts +13 -0
- package/dist/yomeSkills/paths.js +33 -0
- package/dist/yomeSkills/paths.js.map +1 -0
- package/dist/yomeSkills/publish.d.ts +18 -0
- package/dist/yomeSkills/publish.js +114 -0
- package/dist/yomeSkills/publish.js.map +1 -0
- package/dist/yomeSkills/rollback.d.ts +10 -0
- package/dist/yomeSkills/rollback.js +83 -0
- package/dist/yomeSkills/rollback.js.map +1 -0
- package/dist/yomeSkills/search.d.ts +21 -0
- package/dist/yomeSkills/search.js +31 -0
- package/dist/yomeSkills/search.js.map +1 -0
- package/dist/yomeSkills/skillsIndex.d.ts +36 -0
- package/dist/yomeSkills/skillsIndex.js +111 -0
- package/dist/yomeSkills/skillsIndex.js.map +1 -0
- package/dist/yomeSkills/unified.d.ts +53 -0
- package/dist/yomeSkills/unified.js +187 -0
- package/dist/yomeSkills/unified.js.map +1 -0
- package/dist/yomeSkills/uninstall.d.ts +7 -0
- package/dist/yomeSkills/uninstall.js +22 -0
- package/dist/yomeSkills/uninstall.js.map +1 -0
- package/dist/yomeSkills/update.d.ts +18 -0
- package/dist/yomeSkills/update.js +75 -0
- package/dist/yomeSkills/update.js.map +1 -0
- package/dist/yomeSkills/validate.d.ts +11 -0
- package/dist/yomeSkills/validate.js +99 -0
- package/dist/yomeSkills/validate.js.map +1 -0
- 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,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 {};
|