@namzu/cli 29.0.1 → 30.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +194 -0
- package/README.md +20 -0
- package/dist/browser/commands.d.ts +29 -0
- package/dist/browser/commands.d.ts.map +1 -0
- package/dist/browser/commands.js +361 -0
- package/dist/browser/commands.js.map +1 -0
- package/dist/browser/control.d.ts +79 -0
- package/dist/browser/control.d.ts.map +1 -0
- package/dist/browser/control.js +140 -0
- package/dist/browser/control.js.map +1 -0
- package/dist/browser/describe.d.ts +12 -0
- package/dist/browser/describe.d.ts.map +1 -0
- package/dist/browser/describe.js +27 -0
- package/dist/browser/describe.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/acp.d.ts.map +1 -1
- package/dist/commands/acp.js +1 -0
- package/dist/commands/acp.js.map +1 -1
- package/dist/commands/browser.d.ts +7 -0
- package/dist/commands/browser.d.ts.map +1 -0
- package/dist/commands/browser.js +16 -0
- package/dist/commands/browser.js.map +1 -0
- package/dist/commands/drain.d.ts +2 -1
- package/dist/commands/drain.d.ts.map +1 -1
- package/dist/commands/drain.js +6 -3
- package/dist/commands/drain.js.map +1 -1
- package/dist/commands/exec-flags.d.ts +2 -1
- package/dist/commands/exec-flags.d.ts.map +1 -1
- package/dist/commands/exec-flags.js +6 -3
- package/dist/commands/exec-flags.js.map +1 -1
- package/dist/commands/exec-json.d.ts.map +1 -1
- package/dist/commands/exec-json.js +2 -1
- package/dist/commands/exec-json.js.map +1 -1
- package/dist/commands/exec.d.ts.map +1 -1
- package/dist/commands/exec.js +5 -1
- package/dist/commands/exec.js.map +1 -1
- package/dist/commands/host-queries.d.ts.map +1 -1
- package/dist/commands/host-queries.js +10 -3
- package/dist/commands/host-queries.js.map +1 -1
- package/dist/commands/schedule.d.ts +9 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +126 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/serve.d.ts +3 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +5 -3
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/skills.d.ts +10 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +23 -7
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/upgrade.d.ts +5 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +11 -0
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/config/load.d.ts +39 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +232 -1
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +78 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/user-config.d.ts +23 -0
- package/dist/config/user-config.d.ts.map +1 -0
- package/dist/config/user-config.js +48 -0
- package/dist/config/user-config.js.map +1 -0
- package/dist/context/capabilities.d.ts +1 -1
- package/dist/context/capabilities.d.ts.map +1 -1
- package/dist/context/capabilities.js +1 -0
- package/dist/context/capabilities.js.map +1 -1
- package/dist/context/environment.d.ts +26 -3
- package/dist/context/environment.d.ts.map +1 -1
- package/dist/context/environment.js +68 -9
- package/dist/context/environment.js.map +1 -1
- package/dist/doctor/checks/browser.d.ts +15 -0
- package/dist/doctor/checks/browser.d.ts.map +1 -0
- package/dist/doctor/checks/browser.js +63 -0
- package/dist/doctor/checks/browser.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +4 -1
- package/dist/doctor/checks/index.d.ts.map +1 -1
- package/dist/doctor/checks/index.js +8 -1
- package/dist/doctor/checks/index.js.map +1 -1
- package/dist/doctor/checks/scheduler.d.ts +10 -0
- package/dist/doctor/checks/scheduler.d.ts.map +1 -0
- package/dist/doctor/checks/scheduler.js +74 -0
- package/dist/doctor/checks/scheduler.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/notifications/desktop/freedesktop.d.ts +10 -0
- package/dist/integrations/notifications/desktop/freedesktop.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/freedesktop.js +33 -0
- package/dist/integrations/notifications/desktop/freedesktop.js.map +1 -0
- package/dist/integrations/notifications/desktop/macos.d.ts +6 -0
- package/dist/integrations/notifications/desktop/macos.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/macos.js +17 -0
- package/dist/integrations/notifications/desktop/macos.js.map +1 -0
- package/dist/integrations/notifications/desktop/sanitize.d.ts +16 -0
- package/dist/integrations/notifications/desktop/sanitize.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/sanitize.js +49 -0
- package/dist/integrations/notifications/desktop/sanitize.js.map +1 -0
- package/dist/integrations/notifications/desktop/throttle.d.ts +10 -0
- package/dist/integrations/notifications/desktop/throttle.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/throttle.js +39 -0
- package/dist/integrations/notifications/desktop/throttle.js.map +1 -0
- package/dist/integrations/notifications/desktop/windows-toast.d.ts +23 -0
- package/dist/integrations/notifications/desktop/windows-toast.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop/windows-toast.js +56 -0
- package/dist/integrations/notifications/desktop/windows-toast.js.map +1 -0
- package/dist/integrations/notifications/desktop.d.ts +84 -0
- package/dist/integrations/notifications/desktop.d.ts.map +1 -0
- package/dist/integrations/notifications/desktop.js +199 -0
- package/dist/integrations/notifications/desktop.js.map +1 -0
- package/dist/integrations/plugins/runtime.d.ts +8 -2
- package/dist/integrations/plugins/runtime.d.ts.map +1 -1
- package/dist/integrations/plugins/runtime.js +14 -8
- package/dist/integrations/plugins/runtime.js.map +1 -1
- package/dist/integrations/providers/harness-credentials.d.ts +9 -4
- package/dist/integrations/providers/harness-credentials.d.ts.map +1 -1
- package/dist/integrations/providers/harness-credentials.js +16 -8
- package/dist/integrations/providers/harness-credentials.js.map +1 -1
- package/dist/integrations/resident/session-step.d.ts.map +1 -1
- package/dist/integrations/resident/session-step.js +1 -0
- package/dist/integrations/resident/session-step.js.map +1 -1
- package/dist/integrations/subagents/runtime.d.ts +6 -0
- package/dist/integrations/subagents/runtime.d.ts.map +1 -1
- package/dist/integrations/subagents/runtime.js +14 -5
- package/dist/integrations/subagents/runtime.js.map +1 -1
- package/dist/integrations/web/open-url.d.ts +24 -0
- package/dist/integrations/web/open-url.d.ts.map +1 -0
- package/dist/integrations/web/open-url.js +73 -0
- package/dist/integrations/web/open-url.js.map +1 -0
- package/dist/permissions/browser-sites.d.ts +95 -0
- package/dist/permissions/browser-sites.d.ts.map +1 -0
- package/dist/permissions/browser-sites.js +270 -0
- package/dist/permissions/browser-sites.js.map +1 -0
- package/dist/schedule/build.d.ts +86 -0
- package/dist/schedule/build.d.ts.map +1 -0
- package/dist/schedule/build.js +267 -0
- package/dist/schedule/build.js.map +1 -0
- package/dist/schedule/changes.d.ts +28 -0
- package/dist/schedule/changes.d.ts.map +1 -0
- package/dist/schedule/changes.js +65 -0
- package/dist/schedule/changes.js.map +1 -0
- package/dist/schedule/commands/add.d.ts +24 -0
- package/dist/schedule/commands/add.d.ts.map +1 -0
- package/dist/schedule/commands/add.js +447 -0
- package/dist/schedule/commands/add.js.map +1 -0
- package/dist/schedule/commands/args.d.ts +22 -0
- package/dist/schedule/commands/args.d.ts.map +1 -0
- package/dist/schedule/commands/args.js +80 -0
- package/dist/schedule/commands/args.js.map +1 -0
- package/dist/schedule/commands/confirm-prompt.d.ts +6 -0
- package/dist/schedule/commands/confirm-prompt.d.ts.map +1 -0
- package/dist/schedule/commands/confirm-prompt.js +21 -0
- package/dist/schedule/commands/confirm-prompt.js.map +1 -0
- package/dist/schedule/commands/lifecycle.d.ts +39 -0
- package/dist/schedule/commands/lifecycle.d.ts.map +1 -0
- package/dist/schedule/commands/lifecycle.js +586 -0
- package/dist/schedule/commands/lifecycle.js.map +1 -0
- package/dist/schedule/commands/list.d.ts +33 -0
- package/dist/schedule/commands/list.d.ts.map +1 -0
- package/dist/schedule/commands/list.js +206 -0
- package/dist/schedule/commands/list.js.map +1 -0
- package/dist/schedule/commands/logs.d.ts +7 -0
- package/dist/schedule/commands/logs.d.ts.map +1 -0
- package/dist/schedule/commands/logs.js +106 -0
- package/dist/schedule/commands/logs.js.map +1 -0
- package/dist/schedule/commands/service.d.ts +16 -0
- package/dist/schedule/commands/service.d.ts.map +1 -0
- package/dist/schedule/commands/service.js +458 -0
- package/dist/schedule/commands/service.js.map +1 -0
- package/dist/schedule/daemon/daemon.d.ts +156 -0
- package/dist/schedule/daemon/daemon.d.ts.map +1 -0
- package/dist/schedule/daemon/daemon.js +1253 -0
- package/dist/schedule/daemon/daemon.js.map +1 -0
- package/dist/schedule/daemon/endpoint.d.ts +38 -0
- package/dist/schedule/daemon/endpoint.d.ts.map +1 -0
- package/dist/schedule/daemon/endpoint.js +158 -0
- package/dist/schedule/daemon/endpoint.js.map +1 -0
- package/dist/schedule/daemon/exit.d.ts +8 -0
- package/dist/schedule/daemon/exit.d.ts.map +1 -0
- package/dist/schedule/daemon/exit.js +8 -0
- package/dist/schedule/daemon/exit.js.map +1 -0
- package/dist/schedule/daemon/log.d.ts +12 -0
- package/dist/schedule/daemon/log.d.ts.map +1 -0
- package/dist/schedule/daemon/log.js +53 -0
- package/dist/schedule/daemon/log.js.map +1 -0
- package/dist/schedule/daemon/notify.d.ts +38 -0
- package/dist/schedule/daemon/notify.d.ts.map +1 -0
- package/dist/schedule/daemon/notify.js +115 -0
- package/dist/schedule/daemon/notify.js.map +1 -0
- package/dist/schedule/daemon/retention.d.ts +16 -0
- package/dist/schedule/daemon/retention.d.ts.map +1 -0
- package/dist/schedule/daemon/retention.js +46 -0
- package/dist/schedule/daemon/retention.js.map +1 -0
- package/dist/schedule/daemon/sessions.d.ts +23 -0
- package/dist/schedule/daemon/sessions.d.ts.map +1 -0
- package/dist/schedule/daemon/sessions.js +52 -0
- package/dist/schedule/daemon/sessions.js.map +1 -0
- package/dist/schedule/env.d.ts +32 -0
- package/dist/schedule/env.d.ts.map +1 -0
- package/dist/schedule/env.js +106 -0
- package/dist/schedule/env.js.map +1 -0
- package/dist/schedule/fire/browser-preflight.d.ts +41 -0
- package/dist/schedule/fire/browser-preflight.d.ts.map +1 -0
- package/dist/schedule/fire/browser-preflight.js +73 -0
- package/dist/schedule/fire/browser-preflight.js.map +1 -0
- package/dist/schedule/fire/calls.d.ts +49 -0
- package/dist/schedule/fire/calls.d.ts.map +1 -0
- package/dist/schedule/fire/calls.js +114 -0
- package/dist/schedule/fire/calls.js.map +1 -0
- package/dist/schedule/fire/fire.d.ts +78 -0
- package/dist/schedule/fire/fire.d.ts.map +1 -0
- package/dist/schedule/fire/fire.js +490 -0
- package/dist/schedule/fire/fire.js.map +1 -0
- package/dist/schedule/fire/result.d.ts +13 -0
- package/dist/schedule/fire/result.d.ts.map +1 -0
- package/dist/schedule/fire/result.js +18 -0
- package/dist/schedule/fire/result.js.map +1 -0
- package/dist/schedule/fire/unattended-note.d.ts +22 -0
- package/dist/schedule/fire/unattended-note.d.ts.map +1 -0
- package/dist/schedule/fire/unattended-note.js +46 -0
- package/dist/schedule/fire/unattended-note.js.map +1 -0
- package/dist/schedule/floor.d.ts +136 -0
- package/dist/schedule/floor.d.ts.map +1 -0
- package/dist/schedule/floor.js +1289 -0
- package/dist/schedule/floor.js.map +1 -0
- package/dist/schedule/folder.d.ts +34 -0
- package/dist/schedule/folder.d.ts.map +1 -0
- package/dist/schedule/folder.js +84 -0
- package/dist/schedule/folder.js.map +1 -0
- package/dist/schedule/paths.d.ts +49 -0
- package/dist/schedule/paths.d.ts.map +1 -0
- package/dist/schedule/paths.js +53 -0
- package/dist/schedule/paths.js.map +1 -0
- package/dist/schedule/policy.d.ts +141 -0
- package/dist/schedule/policy.d.ts.map +1 -0
- package/dist/schedule/policy.js +378 -0
- package/dist/schedule/policy.js.map +1 -0
- package/dist/schedule/resume-command.d.ts +36 -0
- package/dist/schedule/resume-command.d.ts.map +1 -0
- package/dist/schedule/resume-command.js +72 -0
- package/dist/schedule/resume-command.js.map +1 -0
- package/dist/schedule/service/detect.d.ts +22 -0
- package/dist/schedule/service/detect.d.ts.map +1 -0
- package/dist/schedule/service/detect.js +29 -0
- package/dist/schedule/service/detect.js.map +1 -0
- package/dist/schedule/service/index.d.ts +48 -0
- package/dist/schedule/service/index.d.ts.map +1 -0
- package/dist/schedule/service/index.js +361 -0
- package/dist/schedule/service/index.js.map +1 -0
- package/dist/schedule/service/launchd.d.ts +24 -0
- package/dist/schedule/service/launchd.d.ts.map +1 -0
- package/dist/schedule/service/launchd.js +84 -0
- package/dist/schedule/service/launchd.js.map +1 -0
- package/dist/schedule/service/manifest.d.ts +44 -0
- package/dist/schedule/service/manifest.d.ts.map +1 -0
- package/dist/schedule/service/manifest.js +16 -0
- package/dist/schedule/service/manifest.js.map +1 -0
- package/dist/schedule/service/names.d.ts +9 -0
- package/dist/schedule/service/names.d.ts.map +1 -0
- package/dist/schedule/service/names.js +22 -0
- package/dist/schedule/service/names.js.map +1 -0
- package/dist/schedule/service/quote.d.ts +24 -0
- package/dist/schedule/service/quote.d.ts.map +1 -0
- package/dist/schedule/service/quote.js +64 -0
- package/dist/schedule/service/quote.js.map +1 -0
- package/dist/schedule/service/runner.d.ts +17 -0
- package/dist/schedule/service/runner.d.ts.map +1 -0
- package/dist/schedule/service/runner.js +31 -0
- package/dist/schedule/service/runner.js.map +1 -0
- package/dist/schedule/service/systemd.d.ts +37 -0
- package/dist/schedule/service/systemd.d.ts.map +1 -0
- package/dist/schedule/service/systemd.js +96 -0
- package/dist/schedule/service/systemd.js.map +1 -0
- package/dist/schedule/service/windows-task.d.ts +58 -0
- package/dist/schedule/service/windows-task.d.ts.map +1 -0
- package/dist/schedule/service/windows-task.js +199 -0
- package/dist/schedule/service/windows-task.js.map +1 -0
- package/dist/schedule/service/wsl.d.ts +69 -0
- package/dist/schedule/service/wsl.d.ts.map +1 -0
- package/dist/schedule/service/wsl.js +121 -0
- package/dist/schedule/service/wsl.js.map +1 -0
- package/dist/schedule/store/atomic.d.ts +43 -0
- package/dist/schedule/store/atomic.d.ts.map +1 -0
- package/dist/schedule/store/atomic.js +135 -0
- package/dist/schedule/store/atomic.js.map +1 -0
- package/dist/schedule/store/claims.d.ts +26 -0
- package/dist/schedule/store/claims.d.ts.map +1 -0
- package/dist/schedule/store/claims.js +57 -0
- package/dist/schedule/store/claims.js.map +1 -0
- package/dist/schedule/store/digest.d.ts +18 -0
- package/dist/schedule/store/digest.d.ts.map +1 -0
- package/dist/schedule/store/digest.js +139 -0
- package/dist/schedule/store/digest.js.map +1 -0
- package/dist/schedule/store/history.d.ts +21 -0
- package/dist/schedule/store/history.d.ts.map +1 -0
- package/dist/schedule/store/history.js +114 -0
- package/dist/schedule/store/history.js.map +1 -0
- package/dist/schedule/store/jobs.d.ts +61 -0
- package/dist/schedule/store/jobs.d.ts.map +1 -0
- package/dist/schedule/store/jobs.js +210 -0
- package/dist/schedule/store/jobs.js.map +1 -0
- package/dist/schedule/store/state.d.ts +19 -0
- package/dist/schedule/store/state.d.ts.map +1 -0
- package/dist/schedule/store/state.js +38 -0
- package/dist/schedule/store/state.js.map +1 -0
- package/dist/schedule/types.d.ts +283 -0
- package/dist/schedule/types.d.ts.map +1 -0
- package/dist/schedule/types.js +9 -0
- package/dist/schedule/types.js.map +1 -0
- package/dist/skills/catalog.d.ts +96 -0
- package/dist/skills/catalog.d.ts.map +1 -0
- package/dist/skills/catalog.js +226 -0
- package/dist/skills/catalog.js.map +1 -0
- package/dist/skills/directory.d.ts +38 -0
- package/dist/skills/directory.d.ts.map +1 -0
- package/dist/skills/directory.js +51 -0
- package/dist/skills/directory.js.map +1 -0
- package/dist/skills/save.d.ts +148 -0
- package/dist/skills/save.d.ts.map +1 -0
- package/dist/skills/save.js +344 -0
- package/dist/skills/save.js.map +1 -0
- package/dist/skills/store.d.ts +103 -16
- package/dist/skills/store.d.ts.map +1 -1
- package/dist/skills/store.js +227 -30
- package/dist/skills/store.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +609 -74
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/LiveActivity.d.ts +8 -1
- package/dist/tui/LiveActivity.d.ts.map +1 -1
- package/dist/tui/LiveActivity.js +20 -4
- package/dist/tui/LiveActivity.js.map +1 -1
- package/dist/tui/PermissionOverlay.d.ts +36 -4
- package/dist/tui/PermissionOverlay.d.ts.map +1 -1
- package/dist/tui/PermissionOverlay.js +135 -15
- package/dist/tui/PermissionOverlay.js.map +1 -1
- package/dist/tui/SaveSkillOverlay.d.ts +33 -0
- package/dist/tui/SaveSkillOverlay.d.ts.map +1 -0
- package/dist/tui/SaveSkillOverlay.js +118 -0
- package/dist/tui/SaveSkillOverlay.js.map +1 -0
- package/dist/tui/agent.d.ts +208 -6
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +371 -58
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/browser-notices.d.ts +33 -0
- package/dist/tui/browser-notices.d.ts.map +1 -0
- package/dist/tui/browser-notices.js +102 -0
- package/dist/tui/browser-notices.js.map +1 -0
- package/dist/tui/open-browser.d.ts +29 -1
- package/dist/tui/open-browser.d.ts.map +1 -1
- package/dist/tui/open-browser.js +83 -11
- package/dist/tui/open-browser.js.map +1 -1
- package/dist/tui/permission-review.d.ts +10 -1
- package/dist/tui/permission-review.d.ts.map +1 -1
- package/dist/tui/permission-review.js +228 -22
- package/dist/tui/permission-review.js.map +1 -1
- package/dist/tui/schedule/host-commands.d.ts +34 -0
- package/dist/tui/schedule/host-commands.d.ts.map +1 -0
- package/dist/tui/schedule/host-commands.js +310 -0
- package/dist/tui/schedule/host-commands.js.map +1 -0
- package/dist/tui/schedule/integration.d.ts +62 -0
- package/dist/tui/schedule/integration.d.ts.map +1 -0
- package/dist/tui/schedule/integration.js +145 -0
- package/dist/tui/schedule/integration.js.map +1 -0
- package/dist/tui/schedule/loop-host.d.ts +42 -0
- package/dist/tui/schedule/loop-host.d.ts.map +1 -0
- package/dist/tui/schedule/loop-host.js +153 -0
- package/dist/tui/schedule/loop-host.js.map +1 -0
- package/dist/tui/schedule/resume.d.ts +122 -0
- package/dist/tui/schedule/resume.d.ts.map +1 -0
- package/dist/tui/schedule/resume.js +324 -0
- package/dist/tui/schedule/resume.js.map +1 -0
- package/dist/tui/schedule/startup.d.ts +11 -0
- package/dist/tui/schedule/startup.d.ts.map +1 -0
- package/dist/tui/schedule/startup.js +121 -0
- package/dist/tui/schedule/startup.js.map +1 -0
- package/dist/tui/schedule/tool-host.d.ts +58 -0
- package/dist/tui/schedule/tool-host.d.ts.map +1 -0
- package/dist/tui/schedule/tool-host.js +479 -0
- package/dist/tui/schedule/tool-host.js.map +1 -0
- package/dist/tui/skills/learning.d.ts +74 -0
- package/dist/tui/skills/learning.d.ts.map +1 -0
- package/dist/tui/skills/learning.js +131 -0
- package/dist/tui/skills/learning.js.map +1 -0
- package/dist/tui/skills/suggest-setting.d.ts +22 -0
- package/dist/tui/skills/suggest-setting.d.ts.map +1 -0
- package/dist/tui/skills/suggest-setting.js +55 -0
- package/dist/tui/skills/suggest-setting.js.map +1 -0
- package/dist/tui/skills/suggestion-ledger.d.ts +35 -0
- package/dist/tui/skills/suggestion-ledger.d.ts.map +1 -0
- package/dist/tui/skills/suggestion-ledger.js +52 -0
- package/dist/tui/skills/suggestion-ledger.js.map +1 -0
- package/dist/tui/slashCommands.d.ts +20 -0
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +76 -2
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/turn-interruption.d.ts +20 -1
- package/dist/tui/turn-interruption.d.ts.map +1 -1
- package/dist/tui/turn-interruption.js +43 -0
- package/dist/tui/turn-interruption.js.map +1 -1
- package/dist/tui/types.d.ts +9 -1
- package/dist/tui/types.d.ts.map +1 -1
- package/package.json +7 -5
- package/skills/README.md +20 -0
- package/skills/browser-automation/SKILL.md +84 -0
- package/skills/schedule-task/SKILL.md +146 -0
- package/skills/skill-creator/SKILL.md +101 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `browser.sites`, compiled to the kernel's rule vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* An operator writes one level per site:
|
|
5
|
+
*
|
|
6
|
+
* ```yaml
|
|
7
|
+
* browser:
|
|
8
|
+
* sites:
|
|
9
|
+
* "https://github.com": act
|
|
10
|
+
* "https://*.example.com": read
|
|
11
|
+
* "*": ask
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* and the gate sees `argument_pattern` rules over the two arguments the
|
|
15
|
+
* browser tools canonicalise: `browser.url` (the address a navigation loads)
|
|
16
|
+
* and `browser_act.origin` (the page an action changes). The tools declare
|
|
17
|
+
* `url` as a URL argument, so a rule tests it whole; the SDK's input schema
|
|
18
|
+
* has already turned `HTTPS://GitHub.com.:443/x` into `https://github.com/x`,
|
|
19
|
+
* so one spelling per site is enough.
|
|
20
|
+
*
|
|
21
|
+
* | Level | `browser` navigate / tabs new | `browser_act` |
|
|
22
|
+
* | ------ | ----------------------------- | ------------- |
|
|
23
|
+
* | `deny` | deny | deny |
|
|
24
|
+
* | `read` | allow | deny |
|
|
25
|
+
* | `ask` | review | review |
|
|
26
|
+
* | `act` | allow | allow |
|
|
27
|
+
*
|
|
28
|
+
* Order is the gate's first match: every `deny` first, then the other sites
|
|
29
|
+
* from most to least specific (the same order `@namzu/browser`'s host policy
|
|
30
|
+
* uses, so the gate and the host agree on which key decides), then `*`.
|
|
31
|
+
* Looking at the page (`snapshot`, `screenshot`, `scroll`, `wait_for`, and
|
|
32
|
+
* `tabs list|select|close`) is allowed: the browser tools are network tools,
|
|
33
|
+
* which are reviewed even when read-only unless a rule allows them, and the
|
|
34
|
+
* page being looked at is one the host already let stay loaded.
|
|
35
|
+
*
|
|
36
|
+
* The origin patterns are built here, from the SDK's canonical site key,
|
|
37
|
+
* rather than from a glob: `https://github.com` must not match
|
|
38
|
+
* `https://github.com.evil.example`, `https://evil.example/?https://github.com`
|
|
39
|
+
* or `https://github.com:8443`.
|
|
40
|
+
*/
|
|
41
|
+
import { BROWSER_ACT_TOOL_NAME, BROWSER_TOOL_NAME, canonicalizeBrowserSitePattern, canonicalizeBrowserUrl, } from '@namzu/sdk';
|
|
42
|
+
export const BROWSER_SITE_LEVELS = ['deny', 'read', 'ask', 'act'];
|
|
43
|
+
/** What an unlisted site gets when `*` is not written. */
|
|
44
|
+
export const DEFAULT_BROWSER_SITE_LEVEL = 'ask';
|
|
45
|
+
export function isBrowserSiteLevel(value) {
|
|
46
|
+
return typeof value === 'string' && BROWSER_SITE_LEVELS.includes(value);
|
|
47
|
+
}
|
|
48
|
+
/** A site key as the gate and the host read it: `*`, or the SDK's canonical pattern. */
|
|
49
|
+
export function canonicalBrowserSiteKey(raw) {
|
|
50
|
+
if (raw.trim() === '*')
|
|
51
|
+
return { ok: true, key: '*' };
|
|
52
|
+
const verdict = canonicalizeBrowserSitePattern(raw);
|
|
53
|
+
return verdict.ok ? { ok: true, key: verdict.pattern } : { ok: false, reason: verdict.reason };
|
|
54
|
+
}
|
|
55
|
+
function parseSite(key, level) {
|
|
56
|
+
const match = /^(https?):\/\/(\*\.)?([^:]+)(?::(\*|\d+))?$/.exec(key);
|
|
57
|
+
if (!match)
|
|
58
|
+
return undefined;
|
|
59
|
+
return {
|
|
60
|
+
key,
|
|
61
|
+
level,
|
|
62
|
+
scheme: match[1] ?? '',
|
|
63
|
+
host: match[3] ?? '',
|
|
64
|
+
wildcardHost: match[2] !== undefined,
|
|
65
|
+
port: match[4] ?? '',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Higher is more specific: exact host over wildcard, longer suffix first, exact port over `*`. */
|
|
69
|
+
function specificity(site) {
|
|
70
|
+
return (site.wildcardHost ? 0 : 1_000_000) + site.host.length * 10 + (site.port === '*' ? 0 : 1);
|
|
71
|
+
}
|
|
72
|
+
function escapeRegExp(value) {
|
|
73
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The regex source (unanchored) that matches exactly the canonical origins
|
|
77
|
+
* a site key names. `*.` is one or more whole labels; `:*` is any port or
|
|
78
|
+
* none; no port is the scheme's default only, which the canonical form
|
|
79
|
+
* leaves out.
|
|
80
|
+
*/
|
|
81
|
+
function originSource(site) {
|
|
82
|
+
const host = site.wildcardHost
|
|
83
|
+
? `(?:[^./:?#@\\[\\]]+\\.)+${escapeRegExp(site.host)}`
|
|
84
|
+
: escapeRegExp(site.host);
|
|
85
|
+
const port = site.port === '*' ? '(?::\\d{1,5})?' : site.port === '' ? '' : `:${site.port}`;
|
|
86
|
+
return `${site.scheme}://${host}${port}`;
|
|
87
|
+
}
|
|
88
|
+
const NAVIGATE = {
|
|
89
|
+
deny: 'deny',
|
|
90
|
+
read: 'allow',
|
|
91
|
+
ask: 'review',
|
|
92
|
+
act: 'allow',
|
|
93
|
+
};
|
|
94
|
+
const ACT = {
|
|
95
|
+
deny: 'deny',
|
|
96
|
+
read: 'deny',
|
|
97
|
+
ask: 'review',
|
|
98
|
+
act: 'allow',
|
|
99
|
+
};
|
|
100
|
+
function rulesFor(origin, level) {
|
|
101
|
+
// `*`: any value. `^` alone matches every string the argument can hold.
|
|
102
|
+
const url = origin === undefined ? '^' : `^${origin}(?:[/?#]|$)`;
|
|
103
|
+
const act = origin === undefined ? '^' : `^${origin}$`;
|
|
104
|
+
return [
|
|
105
|
+
{
|
|
106
|
+
type: 'argument_pattern',
|
|
107
|
+
toolNames: [BROWSER_TOOL_NAME],
|
|
108
|
+
argument: 'url',
|
|
109
|
+
pattern: url,
|
|
110
|
+
decision: NAVIGATE[level],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'argument_pattern',
|
|
114
|
+
toolNames: [BROWSER_ACT_TOOL_NAME],
|
|
115
|
+
argument: 'origin',
|
|
116
|
+
pattern: act,
|
|
117
|
+
decision: ACT[level],
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Looking at the page the browser holds. These calls carry no address; the
|
|
123
|
+
* host only ever holds a page the site rules let stay (or `about:blank`).
|
|
124
|
+
* `tabs new` carries a `url` and is decided by the site rules instead.
|
|
125
|
+
*/
|
|
126
|
+
const LOOKING = [
|
|
127
|
+
{
|
|
128
|
+
type: 'argument_pattern',
|
|
129
|
+
toolNames: [BROWSER_TOOL_NAME],
|
|
130
|
+
argument: 'action',
|
|
131
|
+
pattern: '^(?:snapshot|screenshot|scroll|wait_for)$',
|
|
132
|
+
decision: 'allow',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: 'argument_pattern',
|
|
136
|
+
toolNames: [BROWSER_TOOL_NAME],
|
|
137
|
+
argument: 'op',
|
|
138
|
+
pattern: '^(?:list|select|close)$',
|
|
139
|
+
decision: 'allow',
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
/** Canonical keys, `*` filled in, unreadable entries reported. */
|
|
143
|
+
export function normalizeBrowserSites(sites) {
|
|
144
|
+
const out = {};
|
|
145
|
+
const diagnostics = [];
|
|
146
|
+
for (const [raw, level] of Object.entries(sites ?? {})) {
|
|
147
|
+
if (!isBrowserSiteLevel(level)) {
|
|
148
|
+
diagnostics.push(`browser.sites."${raw}": use deny, read, ask or act`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const verdict = canonicalBrowserSiteKey(raw);
|
|
152
|
+
if (!verdict.ok) {
|
|
153
|
+
diagnostics.push(`browser.sites."${raw}": ${verdict.reason}`);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const existing = out[verdict.key];
|
|
157
|
+
// The same site written twice (`https://GitHub.com` and
|
|
158
|
+
// `https://github.com`): the narrower level holds, so a spelling can
|
|
159
|
+
// never widen what another spelling said.
|
|
160
|
+
out[verdict.key] = existing === undefined ? level : narrower(existing, level);
|
|
161
|
+
}
|
|
162
|
+
if (out['*'] === undefined)
|
|
163
|
+
out['*'] = DEFAULT_BROWSER_SITE_LEVEL;
|
|
164
|
+
return { sites: out, diagnostics };
|
|
165
|
+
}
|
|
166
|
+
/** The narrower of two levels: `deny`, then `read`, then `ask`, then `act`. */
|
|
167
|
+
export function narrower(a, b) {
|
|
168
|
+
return BROWSER_SITE_LEVELS.indexOf(a) <= BROWSER_SITE_LEVELS.indexOf(b) ? a : b;
|
|
169
|
+
}
|
|
170
|
+
/** Compile `browser.sites` into gate rules, in the order the gate must try them. */
|
|
171
|
+
export function compileBrowserSites(sites) {
|
|
172
|
+
const normalized = normalizeBrowserSites(sites);
|
|
173
|
+
const diagnostics = [...normalized.diagnostics];
|
|
174
|
+
const parsed = [];
|
|
175
|
+
for (const [key, level] of Object.entries(normalized.sites)) {
|
|
176
|
+
if (key === '*')
|
|
177
|
+
continue;
|
|
178
|
+
const site = parseSite(key, level);
|
|
179
|
+
if (site)
|
|
180
|
+
parsed.push(site);
|
|
181
|
+
else
|
|
182
|
+
diagnostics.push(`browser.sites."${key}": could not be read`);
|
|
183
|
+
}
|
|
184
|
+
const denies = parsed.filter((site) => site.level === 'deny');
|
|
185
|
+
const others = parsed
|
|
186
|
+
.filter((site) => site.level !== 'deny')
|
|
187
|
+
.sort((a, b) => specificity(b) - specificity(a) || (a.key < b.key ? -1 : 1));
|
|
188
|
+
const rules = [
|
|
189
|
+
// A blank tab is where the browser starts; it loads nothing.
|
|
190
|
+
{
|
|
191
|
+
type: 'argument_pattern',
|
|
192
|
+
toolNames: [BROWSER_TOOL_NAME],
|
|
193
|
+
argument: 'url',
|
|
194
|
+
pattern: '^about:blank$',
|
|
195
|
+
decision: 'allow',
|
|
196
|
+
},
|
|
197
|
+
...denies.flatMap((site) => rulesFor(originSource(site), 'deny')),
|
|
198
|
+
...others.flatMap((site) => rulesFor(originSource(site), site.level)),
|
|
199
|
+
...rulesFor(undefined, normalized.sites['*'] ?? DEFAULT_BROWSER_SITE_LEVEL),
|
|
200
|
+
...LOOKING,
|
|
201
|
+
];
|
|
202
|
+
return { rules, sites: normalized.sites, diagnostics };
|
|
203
|
+
}
|
|
204
|
+
const BROWSER_TOOLS = new Set([BROWSER_TOOL_NAME, BROWSER_ACT_TOOL_NAME]);
|
|
205
|
+
/** A `[permissions]` rule that denies a browser tool, which the site rules must not get ahead of. */
|
|
206
|
+
function isBrowserDeny(rule) {
|
|
207
|
+
switch (rule.type) {
|
|
208
|
+
case 'deny_by_name':
|
|
209
|
+
return rule.toolNames.some((name) => BROWSER_TOOLS.has(name));
|
|
210
|
+
case 'argument_pattern':
|
|
211
|
+
return rule.decision === 'deny' && rule.toolNames.some((name) => BROWSER_TOOLS.has(name));
|
|
212
|
+
case 'custom_pattern':
|
|
213
|
+
return (rule.decision === 'deny' &&
|
|
214
|
+
(rule.pattern.startsWith(`^${BROWSER_TOOL_NAME}`) ||
|
|
215
|
+
rule.pattern.startsWith(`^${BROWSER_ACT_TOOL_NAME}`)));
|
|
216
|
+
default:
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The session's rules with the site rules in them: a `[permissions]` deny
|
|
222
|
+
* that names a browser tool first (it still wins), then the site rules, then
|
|
223
|
+
* the rest of the table. An `allow` or `ask` for `browser` in the table is
|
|
224
|
+
* reached only by a call no site rule decided (`back`, `forward`, `reload`).
|
|
225
|
+
*/
|
|
226
|
+
export function withBrowserSiteRules(tableRules, siteRules) {
|
|
227
|
+
return [
|
|
228
|
+
...tableRules.filter(isBrowserDeny),
|
|
229
|
+
...siteRules,
|
|
230
|
+
...tableRules.filter((rule) => !isBrowserDeny(rule)),
|
|
231
|
+
];
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Which key of `sites` decides `origin`, and at what level: a matching
|
|
235
|
+
* `deny` first, else the most specific match, else `*`. The same answer the
|
|
236
|
+
* compiled rules give; used to show the rule on the review screen.
|
|
237
|
+
*/
|
|
238
|
+
export function browserSiteRuleFor(sites, origin) {
|
|
239
|
+
const normalized = normalizeBrowserSites(sites).sites;
|
|
240
|
+
const parsed = Object.entries(normalized)
|
|
241
|
+
.filter(([key]) => key !== '*')
|
|
242
|
+
.map(([key, level]) => parseSite(key, level))
|
|
243
|
+
.filter((site) => site !== undefined);
|
|
244
|
+
const hits = parsed.filter((site) => new RegExp(`^${originSource(site)}$`).test(origin));
|
|
245
|
+
const deny = hits.find((site) => site.level === 'deny');
|
|
246
|
+
if (deny)
|
|
247
|
+
return { site: deny.key, level: 'deny' };
|
|
248
|
+
const best = hits.sort((a, b) => specificity(b) - specificity(a))[0];
|
|
249
|
+
if (best)
|
|
250
|
+
return { site: best.key, level: best.level };
|
|
251
|
+
return { site: '*', level: normalized['*'] ?? DEFAULT_BROWSER_SITE_LEVEL };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The origin a browser call opens or acts on, canonical, or `undefined` for
|
|
255
|
+
* one that names none (`snapshot`, `back`, …).
|
|
256
|
+
*/
|
|
257
|
+
export function browserCallOrigin(toolName, input) {
|
|
258
|
+
if (typeof input !== 'object' || input === null)
|
|
259
|
+
return undefined;
|
|
260
|
+
const record = input;
|
|
261
|
+
if (toolName === BROWSER_ACT_TOOL_NAME) {
|
|
262
|
+
return typeof record.origin === 'string' ? record.origin : undefined;
|
|
263
|
+
}
|
|
264
|
+
if (toolName === BROWSER_TOOL_NAME && typeof record.url === 'string') {
|
|
265
|
+
const verdict = canonicalizeBrowserUrl(record.url);
|
|
266
|
+
return verdict.ok && verdict.url !== 'about:blank' ? verdict.origin : undefined;
|
|
267
|
+
}
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=browser-sites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-sites.js","sourceRoot":"","sources":["../../src/permissions/browser-sites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning what an operator (or a confirmed model proposal) asked for into a
|
|
3
|
+
* job, and what they are shown before they confirm it.
|
|
4
|
+
*
|
|
5
|
+
* Shared by `schedule add`, the TUI and the `schedule` tool's host, so every
|
|
6
|
+
* surface refuses the same things and shows the same preview:
|
|
7
|
+
*
|
|
8
|
+
* - an explicit permission set is required; there is no default;
|
|
9
|
+
* - `unmatched: allow` beside host execution needs `allowUnattendedHost`,
|
|
10
|
+
* which only the CLI flag sets (the tool can never);
|
|
11
|
+
* - the folder is canonicalised and may not be `/`, the home directory, or
|
|
12
|
+
* anything containing or inside `NAMZU_HOME`;
|
|
13
|
+
* - the token budget and the wall clock are always above zero;
|
|
14
|
+
* - the schedule parses in the job's zone and fires at least once.
|
|
15
|
+
*
|
|
16
|
+
* A built job is inert (`pending-confirmation`, no trust) until
|
|
17
|
+
* {@link confirmJob} records who confirmed it and on which surface.
|
|
18
|
+
*/
|
|
19
|
+
import { type ScheduleSpec } from '@namzu/sdk';
|
|
20
|
+
import type { NamzuCliConfig } from '../config/schema.js';
|
|
21
|
+
import type { SchedulePaths } from './paths.js';
|
|
22
|
+
import { type CompiledJobPolicy, type PermissionInput } from './policy.js';
|
|
23
|
+
import type { ConfirmationSurface, ScheduleBudget, ScheduleJob } from './types.js';
|
|
24
|
+
export declare const DEFAULT_TOKEN_BUDGET = 500000;
|
|
25
|
+
export declare const DEFAULT_TIMEOUT_MS: number;
|
|
26
|
+
export declare const DEFAULT_MAX_ITERATIONS = 50;
|
|
27
|
+
/** Below this many iterations a run's preview warns that it may stop unfinished. */
|
|
28
|
+
export declare const FEW_ITERATIONS = 10;
|
|
29
|
+
/** Below this token budget a run's preview warns: one model call resends the whole prompt. */
|
|
30
|
+
export declare const FEW_TOKENS = 50000;
|
|
31
|
+
export declare const DEFAULT_WAIT_FOR_PROVIDER_MS: number;
|
|
32
|
+
export declare const DEFAULT_APPROVAL_TTL_MS: number;
|
|
33
|
+
export declare const DEFAULT_KEEP_SESSIONS = 20;
|
|
34
|
+
export declare const DEFAULT_PAUSE_AFTER_FAILURES = 5;
|
|
35
|
+
export interface JobRequest {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly prompt: string;
|
|
38
|
+
readonly when: string;
|
|
39
|
+
/** A spec already parsed (an edit that keeps its schedule); `when` is then ignored. */
|
|
40
|
+
readonly spec?: ScheduleSpec;
|
|
41
|
+
readonly folder: string;
|
|
42
|
+
readonly tz?: string;
|
|
43
|
+
readonly permissions: PermissionInput;
|
|
44
|
+
readonly budget?: Partial<ScheduleBudget>;
|
|
45
|
+
/** `provider` or `provider/model`; absent: the operator's configured primary. */
|
|
46
|
+
readonly model?: string;
|
|
47
|
+
readonly effort?: string;
|
|
48
|
+
readonly includeSummary?: boolean;
|
|
49
|
+
readonly keepSessions?: number;
|
|
50
|
+
readonly pauseAfterFailures?: number;
|
|
51
|
+
readonly approvalTtlMs?: number;
|
|
52
|
+
readonly createdBy: ScheduleJob['createdBy'];
|
|
53
|
+
/** Only the CLI's `--allow-unattended-host` sets this. */
|
|
54
|
+
readonly allowUnattendedHost?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare class JobRequestError extends Error {
|
|
57
|
+
readonly name = "JobRequestError";
|
|
58
|
+
}
|
|
59
|
+
/** The model a job pins: `provider[/model]`, or the configured primary. */
|
|
60
|
+
export declare function resolveJobModel(spec: string | undefined, home?: string): ScheduleJob['model'];
|
|
61
|
+
export declare function buildJob(request: JobRequest, context: {
|
|
62
|
+
readonly paths: SchedulePaths;
|
|
63
|
+
readonly config: Pick<NamzuCliConfig, 'limits'>;
|
|
64
|
+
readonly now: Date;
|
|
65
|
+
readonly osHome?: string;
|
|
66
|
+
}): ScheduleJob;
|
|
67
|
+
/**
|
|
68
|
+
* Record a confirmation: trust for the job's folder (for this job only —
|
|
69
|
+
* `trust.json` is not touched), the digest of what was confirmed, and the
|
|
70
|
+
* surface it happened on. A non-interactive surface confirms nothing.
|
|
71
|
+
*/
|
|
72
|
+
export declare function confirmJob(job: ScheduleJob, surface: ConfirmationSurface, now: Date, options?: {
|
|
73
|
+
readonly paused?: boolean;
|
|
74
|
+
}): ScheduleJob;
|
|
75
|
+
/**
|
|
76
|
+
* An edit: `current` with what `rebuilt` (the job built again from the
|
|
77
|
+
* edited request) says, and everything that makes it the same job kept —
|
|
78
|
+
* its id, name, creation, revision and state. The caller confirms it again
|
|
79
|
+
* and writes it with `updateJob`, so its history carries on.
|
|
80
|
+
*/
|
|
81
|
+
export declare function editedJob(current: ScheduleJob, rebuilt: ScheduleJob): ScheduleJob;
|
|
82
|
+
/** At most how many times a day the schedule fires (the busiest of the next seven days). */
|
|
83
|
+
export declare function runsPerDay(spec: ScheduleSpec, now: Date): number;
|
|
84
|
+
/** The job as a person is asked to confirm it. Every line is computed here, never taken from a proposal. */
|
|
85
|
+
export declare function previewLines(job: ScheduleJob, policy: CompiledJobPolicy, now: Date): string[];
|
|
86
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/schedule/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning what an operator (or a confirmed model proposal) asked for into a
|
|
3
|
+
* job, and what they are shown before they confirm it.
|
|
4
|
+
*
|
|
5
|
+
* Shared by `schedule add`, the TUI and the `schedule` tool's host, so every
|
|
6
|
+
* surface refuses the same things and shows the same preview:
|
|
7
|
+
*
|
|
8
|
+
* - an explicit permission set is required; there is no default;
|
|
9
|
+
* - `unmatched: allow` beside host execution needs `allowUnattendedHost`,
|
|
10
|
+
* which only the CLI flag sets (the tool can never);
|
|
11
|
+
* - the folder is canonicalised and may not be `/`, the home directory, or
|
|
12
|
+
* anything containing or inside `NAMZU_HOME`;
|
|
13
|
+
* - the token budget and the wall clock are always above zero;
|
|
14
|
+
* - the schedule parses in the job's zone and fires at least once.
|
|
15
|
+
*
|
|
16
|
+
* A built job is inert (`pending-confirmation`, no trust) until
|
|
17
|
+
* {@link confirmJob} records who confirmed it and on which surface.
|
|
18
|
+
*/
|
|
19
|
+
import { SCHEDULE_CATCH_UP_WINDOW_MS, countOccurrences, describeSchedule, generateScheduleJobId, hostTimeZone, parseScheduleSpec, upcomingFireTimes, validateTimeZone, } from '@namzu/sdk';
|
|
20
|
+
import { PROVIDER_REGISTRY, readPreferences, } from '../integrations/providers/index.js';
|
|
21
|
+
import { checkJobFolder } from './folder.js';
|
|
22
|
+
import { expandPermissions } from './policy.js';
|
|
23
|
+
import { computeProjectDigest } from './store/digest.js';
|
|
24
|
+
import { JOB_NAME, jobSecurityDigest } from './store/jobs.js';
|
|
25
|
+
export const DEFAULT_TOKEN_BUDGET = 500_000;
|
|
26
|
+
export const DEFAULT_TIMEOUT_MS = 30 * 60_000;
|
|
27
|
+
export const DEFAULT_MAX_ITERATIONS = 50;
|
|
28
|
+
/** Below this many iterations a run's preview warns that it may stop unfinished. */
|
|
29
|
+
export const FEW_ITERATIONS = 10;
|
|
30
|
+
/** Below this token budget a run's preview warns: one model call resends the whole prompt. */
|
|
31
|
+
export const FEW_TOKENS = 50_000;
|
|
32
|
+
export const DEFAULT_WAIT_FOR_PROVIDER_MS = 10 * 60_000;
|
|
33
|
+
export const DEFAULT_APPROVAL_TTL_MS = 7 * 24 * 60 * 60_000;
|
|
34
|
+
export const DEFAULT_KEEP_SESSIONS = 20;
|
|
35
|
+
export const DEFAULT_PAUSE_AFTER_FAILURES = 5;
|
|
36
|
+
export class JobRequestError extends Error {
|
|
37
|
+
name = 'JobRequestError';
|
|
38
|
+
}
|
|
39
|
+
function positive(label, value, fallback) {
|
|
40
|
+
const v = value ?? fallback;
|
|
41
|
+
if (!Number.isSafeInteger(v) || v <= 0)
|
|
42
|
+
throw new JobRequestError(`${label} must be a whole number above zero`);
|
|
43
|
+
return v;
|
|
44
|
+
}
|
|
45
|
+
/** The model a job pins: `provider[/model]`, or the configured primary. */
|
|
46
|
+
export function resolveJobModel(spec, home) {
|
|
47
|
+
if (spec) {
|
|
48
|
+
const [provider = '', ...rest] = spec.split('/');
|
|
49
|
+
if (!(provider in PROVIDER_REGISTRY)) {
|
|
50
|
+
throw new JobRequestError(`unknown provider "${provider}" (known: ${Object.keys(PROVIDER_REGISTRY).join(', ')})`);
|
|
51
|
+
}
|
|
52
|
+
const model = rest.join('/');
|
|
53
|
+
return {
|
|
54
|
+
provider,
|
|
55
|
+
...(model ? { model } : { model: PROVIDER_REGISTRY[provider].defaultModel }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const read = readPreferences(home);
|
|
59
|
+
const primary = read.status === 'ok' ? read.prefs.providers[0] : undefined;
|
|
60
|
+
if (!primary) {
|
|
61
|
+
throw new JobRequestError('no provider is configured; pass --model <provider>/<model> or pick one in namzu first');
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
provider: primary.id,
|
|
65
|
+
model: primary.model ?? PROVIDER_REGISTRY[primary.id].defaultModel,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function buildJob(request, context) {
|
|
69
|
+
if (!JOB_NAME.test(request.name)) {
|
|
70
|
+
throw new JobRequestError(`"${request.name}" is not a job name: lowercase letters, digits and dashes, starting with a letter or digit`);
|
|
71
|
+
}
|
|
72
|
+
if (!request.prompt.trim())
|
|
73
|
+
throw new JobRequestError('the prompt is empty');
|
|
74
|
+
const permissions = (() => {
|
|
75
|
+
try {
|
|
76
|
+
return expandPermissions(request.permissions);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw new JobRequestError(error instanceof Error ? error.message : String(error));
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
if (permissions.unmatched === 'allow' &&
|
|
83
|
+
permissions.execution === 'host' &&
|
|
84
|
+
!request.allowUnattendedHost) {
|
|
85
|
+
throw new JobRequestError('unmatched: allow with execution on the host lets an unattended run do anything no rule forbids; pass --allow-unattended-host to mean it, or use --execution sandbox');
|
|
86
|
+
}
|
|
87
|
+
const folder = checkJobFolder(request.folder, {
|
|
88
|
+
namzuHome: context.paths.home,
|
|
89
|
+
...(context.osHome ? { osHome: context.osHome } : {}),
|
|
90
|
+
});
|
|
91
|
+
if (!folder.ok)
|
|
92
|
+
throw new JobRequestError(folder.reason);
|
|
93
|
+
const extra = (permissions.additionalDirectories ?? []).map((dir) => {
|
|
94
|
+
const checked = checkJobFolder(dir, {
|
|
95
|
+
namzuHome: context.paths.home,
|
|
96
|
+
...(context.osHome ? { osHome: context.osHome } : {}),
|
|
97
|
+
});
|
|
98
|
+
if (!checked.ok)
|
|
99
|
+
throw new JobRequestError(`additional directory: ${checked.reason}`);
|
|
100
|
+
return checked.canonical;
|
|
101
|
+
});
|
|
102
|
+
const tz = validateTimeZone(request.tz ?? hostTimeZone());
|
|
103
|
+
let spec;
|
|
104
|
+
try {
|
|
105
|
+
spec = request.spec ?? parseScheduleSpec(request.when, { now: context.now, tz });
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new JobRequestError(error instanceof Error ? error.message : String(error));
|
|
109
|
+
}
|
|
110
|
+
const limits = context.config.limits ?? {};
|
|
111
|
+
const budget = {
|
|
112
|
+
maxIterations: positive('max iterations', request.budget?.maxIterations, limits.maxIterations || DEFAULT_MAX_ITERATIONS),
|
|
113
|
+
tokenBudget: positive('the token budget', request.budget?.tokenBudget, limits.tokenBudget || DEFAULT_TOKEN_BUDGET),
|
|
114
|
+
timeoutMs: positive('the timeout', request.budget?.timeoutMs, limits.timeoutMs || DEFAULT_TIMEOUT_MS),
|
|
115
|
+
waitForProviderMs: request.budget?.waitForProviderMs ?? limits.waitForProviderMs ?? DEFAULT_WAIT_FOR_PROVIDER_MS,
|
|
116
|
+
};
|
|
117
|
+
if (budget.timeoutMs > 2_147_483_647 - 60_000)
|
|
118
|
+
throw new JobRequestError('the timeout is too long');
|
|
119
|
+
const at = context.now.toISOString();
|
|
120
|
+
return {
|
|
121
|
+
v: 1,
|
|
122
|
+
kind: 'schedule-job',
|
|
123
|
+
id: generateScheduleJobId(),
|
|
124
|
+
name: request.name,
|
|
125
|
+
revision: 0,
|
|
126
|
+
createdAt: at,
|
|
127
|
+
updatedAt: at,
|
|
128
|
+
createdBy: request.createdBy,
|
|
129
|
+
prompt: request.prompt,
|
|
130
|
+
folder: { path: request.folder, canonical: folder.canonical },
|
|
131
|
+
trust: null,
|
|
132
|
+
schedule: spec,
|
|
133
|
+
permissions: { ...permissions, ...(extra.length > 0 ? { additionalDirectories: extra } : {}) },
|
|
134
|
+
budget,
|
|
135
|
+
model: {
|
|
136
|
+
...resolveJobModel(request.model, context.paths.home),
|
|
137
|
+
...(request.effort ? { effort: request.effort } : {}),
|
|
138
|
+
},
|
|
139
|
+
catchUp: { windowMs: SCHEDULE_CATCH_UP_WINDOW_MS },
|
|
140
|
+
notify: {
|
|
141
|
+
finished: true,
|
|
142
|
+
failed: true,
|
|
143
|
+
awaitingApproval: true,
|
|
144
|
+
includeSummary: request.includeSummary === true,
|
|
145
|
+
},
|
|
146
|
+
failurePolicy: {
|
|
147
|
+
pauseAfterFailures: request.pauseAfterFailures ?? DEFAULT_PAUSE_AFTER_FAILURES,
|
|
148
|
+
},
|
|
149
|
+
retention: { keepSessions: request.keepSessions ?? DEFAULT_KEEP_SESSIONS },
|
|
150
|
+
state: 'pending-confirmation',
|
|
151
|
+
approvalTtlMs: request.approvalTtlMs ?? DEFAULT_APPROVAL_TTL_MS,
|
|
152
|
+
projectDigest: computeProjectDigest(folder.canonical),
|
|
153
|
+
confirmation: null,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Record a confirmation: trust for the job's folder (for this job only —
|
|
158
|
+
* `trust.json` is not touched), the digest of what was confirmed, and the
|
|
159
|
+
* surface it happened on. A non-interactive surface confirms nothing.
|
|
160
|
+
*/
|
|
161
|
+
export function confirmJob(job, surface, now, options = {}) {
|
|
162
|
+
if (surface === 'cli-noninteractive')
|
|
163
|
+
return { ...job, state: 'pending-confirmation', confirmation: null };
|
|
164
|
+
const at = now.toISOString();
|
|
165
|
+
const trusted = {
|
|
166
|
+
...job,
|
|
167
|
+
trust: { canonical: job.folder.canonical, grantedAt: at, by: 'operator-confirmation' },
|
|
168
|
+
projectDigest: computeProjectDigest(job.folder.canonical),
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
...trusted,
|
|
172
|
+
state: options.paused ? 'paused' : 'active',
|
|
173
|
+
...(options.paused ? { pausedAt: at, pausedBy: 'operator' } : {}),
|
|
174
|
+
confirmation: { at, surface, digest: jobSecurityDigest(trusted) },
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* An edit: `current` with what `rebuilt` (the job built again from the
|
|
179
|
+
* edited request) says, and everything that makes it the same job kept —
|
|
180
|
+
* its id, name, creation, revision and state. The caller confirms it again
|
|
181
|
+
* and writes it with `updateJob`, so its history carries on.
|
|
182
|
+
*/
|
|
183
|
+
export function editedJob(current, rebuilt) {
|
|
184
|
+
return {
|
|
185
|
+
...current,
|
|
186
|
+
prompt: rebuilt.prompt,
|
|
187
|
+
folder: rebuilt.folder,
|
|
188
|
+
schedule: rebuilt.schedule,
|
|
189
|
+
permissions: rebuilt.permissions,
|
|
190
|
+
budget: rebuilt.budget,
|
|
191
|
+
model: rebuilt.model,
|
|
192
|
+
notify: rebuilt.notify,
|
|
193
|
+
failurePolicy: rebuilt.failurePolicy,
|
|
194
|
+
retention: rebuilt.retention,
|
|
195
|
+
approvalTtlMs: rebuilt.approvalTtlMs,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** At most how many times a day the schedule fires (the busiest of the next seven days). */
|
|
199
|
+
export function runsPerDay(spec, now) {
|
|
200
|
+
if (spec.kind === 'at')
|
|
201
|
+
return 1;
|
|
202
|
+
if (spec.kind === 'every')
|
|
203
|
+
return Math.ceil((24 * 60 * 60_000) / spec.everyMs);
|
|
204
|
+
let most = 0;
|
|
205
|
+
for (let d = 0; d < 7; d++) {
|
|
206
|
+
const from = new Date(now.getTime() + d * 24 * 60 * 60_000);
|
|
207
|
+
const to = new Date(from.getTime() + 24 * 60 * 60_000);
|
|
208
|
+
most = Math.max(most, countOccurrences(spec, from, to).count);
|
|
209
|
+
}
|
|
210
|
+
return most;
|
|
211
|
+
}
|
|
212
|
+
function duration(ms) {
|
|
213
|
+
if (ms % 86_400_000 === 0)
|
|
214
|
+
return `${ms / 86_400_000} d`;
|
|
215
|
+
if (ms % 3_600_000 === 0)
|
|
216
|
+
return `${ms / 3_600_000} h`;
|
|
217
|
+
if (ms % 60_000 === 0)
|
|
218
|
+
return `${ms / 60_000} min`;
|
|
219
|
+
return `${Math.round(ms / 1000)} s`;
|
|
220
|
+
}
|
|
221
|
+
/** The job as a person is asked to confirm it. Every line is computed here, never taken from a proposal. */
|
|
222
|
+
export function previewLines(job, policy, now) {
|
|
223
|
+
const tz = job.schedule.kind === 'cron' ? job.schedule.tz : hostTimeZone();
|
|
224
|
+
const next = upcomingFireTimes(job.schedule, now, 3).map((t) => new Intl.DateTimeFormat('en-GB', {
|
|
225
|
+
dateStyle: 'medium',
|
|
226
|
+
timeStyle: 'short',
|
|
227
|
+
timeZone: tz,
|
|
228
|
+
}).format(t));
|
|
229
|
+
const perDay = runsPerDay(job.schedule, now);
|
|
230
|
+
return [
|
|
231
|
+
`Job ${job.name}`,
|
|
232
|
+
`Folder ${job.folder.canonical}`,
|
|
233
|
+
`When ${describeSchedule(job.schedule, { tz })}`,
|
|
234
|
+
`Next ${next.length > 0 ? next.join(' · ') : 'never'}`,
|
|
235
|
+
`Model ${job.model.provider}${job.model.model ? `/${job.model.model}` : ''}${job.model.effort ? ` (${job.model.effort})` : ''}`,
|
|
236
|
+
`Budget ${job.budget.tokenBudget.toLocaleString('en-US')} tokens, ${job.budget.maxIterations} iterations, ${duration(job.budget.timeoutMs)} per run`,
|
|
237
|
+
// A proposal once set 1, read as "one post per run": the first run
|
|
238
|
+
// stopped after its first model call, with nothing done.
|
|
239
|
+
...(job.budget.maxIterations < FEW_ITERATIONS
|
|
240
|
+
? [
|
|
241
|
+
`Warning ${job.budget.maxIterations} iteration${job.budget.maxIterations === 1 ? '' : 's'} is one model call${job.budget.maxIterations === 1 ? '' : ' each'} with its tool calls; most tasks need more (the default is ${DEFAULT_MAX_ITERATIONS}), and a run that runs out stops unfinished`,
|
|
242
|
+
]
|
|
243
|
+
: []),
|
|
244
|
+
// A proposal once set 4,000 tokens for a job whose runs each took
|
|
245
|
+
// about 110,000: every model call resends the whole prompt.
|
|
246
|
+
...(job.budget.tokenBudget < FEW_TOKENS
|
|
247
|
+
? [
|
|
248
|
+
`Warning ${job.budget.tokenBudget.toLocaleString('en-US')} tokens may not cover even a few model calls, each of which resends the whole prompt; a run that runs out stops unfinished (the default is ${DEFAULT_TOKEN_BUDGET.toLocaleString('en-US')})`,
|
|
249
|
+
]
|
|
250
|
+
: []),
|
|
251
|
+
`Ceiling up to ${perDay} run${perDay === 1 ? '' : 's'} a day × ${job.budget.tokenBudget.toLocaleString('en-US')} tokens = ${(perDay * job.budget.tokenBudget).toLocaleString('en-US')} tokens a day`,
|
|
252
|
+
`Runs on ${job.permissions.execution === 'host' ? 'this machine (host)' : 'the sandbox'}`,
|
|
253
|
+
...(policy.network ? ['Network THIS RUN CAN REACH THE NETWORK'] : []),
|
|
254
|
+
...(job.permissions.browser
|
|
255
|
+
? [
|
|
256
|
+
`Browser SIGNED IN AS YOU: profile ${job.permissions.browser.profile}, only ${Object.keys(job.permissions.browser.sites).join(', ')}`,
|
|
257
|
+
]
|
|
258
|
+
: []),
|
|
259
|
+
...(job.permissions.unmatched === 'allow'
|
|
260
|
+
? ['Unmatched CALLS NO RULE COVERS RUN WITHOUT ASKING']
|
|
261
|
+
: []),
|
|
262
|
+
'Permissions',
|
|
263
|
+
...policy.lines.map((line) => ` ${line}`),
|
|
264
|
+
`Approvals a call that waits for you expires after ${duration(job.approvalTtlMs)}`,
|
|
265
|
+
];
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=build.js.map
|