@cjhyy/code-shell-core 0.5.0-rc.1 → 0.5.0-rc.2
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/dist/agent/agent-definition-registry.d.ts +18 -3
- package/dist/agent/agent-definition-registry.js +47 -18
- package/dist/agent/agent-definition.d.ts +17 -0
- package/dist/agent/agent-definition.js +22 -1
- package/dist/arena/arena.js +11 -12
- package/dist/arena/context/context-tools.js +2 -4
- package/dist/arena/context/within-root.d.ts +7 -0
- package/dist/arena/context/within-root.js +15 -0
- package/dist/arena/iterate/phases/argue.js +8 -2
- package/dist/arena/iterate/phases/revise.js +1 -1
- package/dist/arena/iterate/phases/tournament.js +3 -3
- package/dist/arena/phases/adjudication.js +1 -4
- package/dist/arena/phases/build-consensus.js +1 -4
- package/dist/arena/phases/cross-review.js +2 -8
- package/dist/arena/phases/debate-rounds.js +1 -4
- package/dist/arena/phases/participant-research.js +1 -4
- package/dist/arena/phases/planning-detail-expansion.js +8 -10
- package/dist/arena/planner.js +0 -1
- package/dist/arena/providers/docs.d.ts +1 -0
- package/dist/arena/providers/docs.js +5 -2
- package/dist/arena/providers/repo.d.ts +1 -0
- package/dist/arena/providers/repo.js +5 -2
- package/dist/arena/strategies/utils.js +36 -3
- package/dist/arena/transitions.d.ts +7 -2
- package/dist/arena/transitions.js +9 -4
- package/dist/arena/types.d.ts +8 -2
- package/dist/automation/cron-expr.d.ts +31 -0
- package/dist/automation/cron-expr.js +151 -0
- package/dist/automation/index.d.ts +41 -0
- package/dist/automation/index.js +39 -0
- package/dist/automation/runner.d.ts +67 -0
- package/dist/automation/runner.js +56 -0
- package/dist/automation/scheduler.d.ts +156 -0
- package/dist/automation/scheduler.js +546 -0
- package/dist/automation/store.d.ts +39 -0
- package/dist/automation/store.js +119 -0
- package/dist/automation/write-policy.d.ts +34 -0
- package/dist/automation/write-policy.js +113 -0
- package/dist/automation/write-run.d.ts +51 -0
- package/dist/automation/write-run.js +38 -0
- package/dist/capability-control/index.d.ts +5 -0
- package/dist/capability-control/index.js +3 -0
- package/dist/capability-control/overlay.d.ts +49 -0
- package/dist/capability-control/overlay.js +89 -0
- package/dist/capability-control/project.d.ts +65 -0
- package/dist/capability-control/project.js +147 -0
- package/dist/capability-control/service.d.ts +70 -0
- package/dist/capability-control/service.js +147 -0
- package/dist/capability-control/types.d.ts +62 -0
- package/dist/capability-control/types.js +17 -0
- package/dist/cli/agent-server-stdio.d.ts +12 -1
- package/dist/cli/agent-server-stdio.js +114 -19
- package/dist/cli/agent-server-tcp.d.ts +20 -0
- package/dist/cli/agent-server-tcp.js +120 -0
- package/dist/cli/graceful-shutdown.d.ts +27 -0
- package/dist/cli/graceful-shutdown.js +30 -0
- package/dist/context/compaction.js +23 -15
- package/dist/context/manager.d.ts +0 -20
- package/dist/context/manager.js +0 -37
- package/dist/cron/cron-runtime.d.ts +2 -0
- package/dist/cron/cron-runtime.js +2 -0
- package/dist/cron/cron-store.d.ts +2 -0
- package/dist/cron/cron-store.js +2 -0
- package/dist/cron/scheduler.d.ts +5 -32
- package/dist/cron/scheduler.js +5 -113
- package/dist/data/openrouter-sync.js +1 -1
- package/dist/engine/engine.d.ts +208 -14
- package/dist/engine/engine.js +754 -169
- package/dist/engine/goal.d.ts +42 -0
- package/dist/engine/goal.js +52 -0
- package/dist/engine/image-compression.d.ts +81 -0
- package/dist/engine/image-compression.js +186 -0
- package/dist/engine/image-policy.d.ts +152 -0
- package/dist/engine/image-policy.js +165 -0
- package/dist/engine/reactive-threshold.d.ts +13 -0
- package/dist/engine/reactive-threshold.js +17 -0
- package/dist/engine/runtime.js +7 -0
- package/dist/engine/session-title.d.ts +13 -0
- package/dist/engine/session-title.js +34 -0
- package/dist/engine/turn-loop.d.ts +29 -8
- package/dist/engine/turn-loop.js +498 -316
- package/dist/git/parse-log.d.ts +13 -0
- package/dist/git/parse-log.js +21 -0
- package/dist/git/utils.d.ts +8 -6
- package/dist/git/utils.js +57 -26
- package/dist/git/worktree.js +33 -18
- package/dist/hooks/events.d.ts +23 -1
- package/dist/hooks/goal-stop-hook.d.ts +30 -0
- package/dist/hooks/goal-stop-hook.js +102 -0
- package/dist/hooks/hook-output.d.ts +33 -0
- package/dist/hooks/hook-output.js +79 -0
- package/dist/hooks/registry.d.ts +7 -0
- package/dist/hooks/registry.js +38 -1
- package/dist/hooks/shell-runner.d.ts +2 -0
- package/dist/hooks/shell-runner.js +43 -2
- package/dist/index.d.ts +31 -6
- package/dist/index.js +30 -3
- package/dist/llm/capabilities/reasoning-control.d.ts +24 -0
- package/dist/llm/capabilities/reasoning-control.js +38 -0
- package/dist/llm/capabilities/rules.js +33 -3
- package/dist/llm/capabilities/types.d.ts +22 -2
- package/dist/llm/clamp-max-tokens.d.ts +11 -0
- package/dist/llm/clamp-max-tokens.js +17 -0
- package/dist/llm/client-base.d.ts +41 -4
- package/dist/llm/client-base.js +67 -13
- package/dist/llm/client-factory.d.ts +3 -3
- package/dist/llm/client-factory.js +2 -2
- package/dist/llm/model-pool.d.ts +15 -11
- package/dist/llm/model-pool.js +23 -20
- package/dist/llm/provider-catalog.d.ts +2 -2
- package/dist/llm/providers/anthropic.d.ts +32 -2
- package/dist/llm/providers/anthropic.js +147 -8
- package/dist/llm/providers/openai.d.ts +11 -2
- package/dist/llm/providers/openai.js +253 -52
- package/dist/llm/reasoning-setting.d.ts +51 -0
- package/dist/llm/reasoning-setting.js +32 -0
- package/dist/llm/stop-reason.d.ts +13 -0
- package/dist/llm/stop-reason.js +21 -0
- package/dist/llm/strip-vision.d.ts +32 -0
- package/dist/llm/strip-vision.js +94 -0
- package/dist/llm/types.d.ts +5 -6
- package/dist/logging/logger.js +18 -4
- package/dist/logging/sanitize-messages.d.ts +10 -0
- package/dist/logging/sanitize-messages.js +90 -0
- package/dist/lsp/client.js +28 -8
- package/dist/lsp/manager.js +2 -1
- package/dist/lsp/root-path.d.ts +9 -0
- package/dist/lsp/root-path.js +12 -0
- package/dist/onboarding.js +18 -11
- package/dist/plugins/gitOps.d.ts +34 -0
- package/dist/plugins/gitOps.js +59 -3
- package/dist/plugins/installer/codex/convertAgents.d.ts +7 -0
- package/dist/plugins/installer/codex/convertAgents.js +55 -0
- package/dist/plugins/installer/codex/convertMcp.d.ts +8 -0
- package/dist/plugins/installer/codex/convertMcp.js +45 -0
- package/dist/plugins/installer/codex/convertSkills.d.ts +12 -0
- package/dist/plugins/installer/codex/convertSkills.js +33 -0
- package/dist/plugins/installer/detectFormat.d.ts +2 -0
- package/dist/plugins/installer/detectFormat.js +6 -0
- package/dist/plugins/installer/install.d.ts +7 -0
- package/dist/plugins/installer/install.js +99 -0
- package/dist/plugins/installer/installFromSource.d.ts +13 -0
- package/dist/plugins/installer/installFromSource.js +45 -0
- package/dist/plugins/installer/list.d.ts +9 -0
- package/dist/plugins/installer/list.js +30 -0
- package/dist/plugins/installer/loadPluginAgents.d.ts +3 -0
- package/dist/plugins/installer/loadPluginAgents.js +23 -0
- package/dist/plugins/installer/loadPluginMcp.d.ts +7 -0
- package/dist/plugins/installer/loadPluginMcp.js +74 -0
- package/dist/plugins/installer/parseSource.d.ts +20 -0
- package/dist/plugins/installer/parseSource.js +74 -0
- package/dist/plugins/installer/paths.d.ts +5 -0
- package/dist/plugins/installer/paths.js +25 -0
- package/dist/plugins/installer/types.d.ts +49 -0
- package/dist/plugins/installer/types.js +27 -0
- package/dist/plugins/installer/uninstall.d.ts +2 -0
- package/dist/plugins/installer/uninstall.js +14 -0
- package/dist/plugins/installer/update.d.ts +14 -0
- package/dist/plugins/installer/update.js +65 -0
- package/dist/plugins/loadPluginHooks.d.ts +8 -1
- package/dist/plugins/loadPluginHooks.js +11 -1
- package/dist/plugins/marketplaceManager.d.ts +8 -1
- package/dist/plugins/marketplaceManager.js +38 -4
- package/dist/plugins/pluginCommandHook.js +34 -0
- package/dist/plugins/pluginInstaller.d.ts +21 -0
- package/dist/plugins/pluginInstaller.js +128 -29
- package/dist/plugins/schemas.js +40 -6
- package/dist/plugins/types.d.ts +4 -0
- package/dist/preset/index.js +16 -0
- package/dist/prompt/composer.d.ts +4 -0
- package/dist/prompt/composer.js +28 -4
- package/dist/prompt/sections/orchestration.md +8 -0
- package/dist/protocol/chat-session-manager.d.ts +8 -1
- package/dist/protocol/chat-session-manager.js +10 -0
- package/dist/protocol/chat-session.d.ts +17 -0
- package/dist/protocol/chat-session.js +28 -0
- package/dist/protocol/redact.d.ts +50 -0
- package/dist/protocol/redact.js +71 -0
- package/dist/protocol/server.d.ts +41 -2
- package/dist/protocol/server.js +231 -33
- package/dist/protocol/tcp-transport.d.ts +45 -0
- package/dist/protocol/tcp-transport.js +74 -0
- package/dist/protocol/types.d.ts +23 -0
- package/dist/protocol/types.js +6 -0
- package/dist/remote/bridge.d.ts +11 -2
- package/dist/remote/bridge.js +61 -33
- package/dist/run/ArtifactTracker.js +5 -4
- package/dist/run/EngineRunner.d.ts +27 -1
- package/dist/run/EngineRunner.js +46 -8
- package/dist/run/FileRunStore.js +32 -8
- package/dist/run/RunLock.d.ts +28 -2
- package/dist/run/RunLock.js +49 -7
- package/dist/run/RunManager.js +51 -3
- package/dist/run/RunQueue.d.ts +1 -0
- package/dist/run/RunQueue.js +8 -2
- package/dist/run/factory.d.ts +7 -0
- package/dist/run/factory.js +1 -0
- package/dist/run/index.d.ts +2 -2
- package/dist/run/index.js +1 -1
- package/dist/run/redirect-target.d.ts +7 -0
- package/dist/run/redirect-target.js +13 -0
- package/dist/run/types.js +1 -1
- package/dist/services/browser-open.d.ts +13 -0
- package/dist/services/browser-open.js +16 -0
- package/dist/services/dream-consolidation.d.ts +57 -0
- package/dist/services/dream-consolidation.js +151 -0
- package/dist/services/memory-orchestrator.js +18 -0
- package/dist/services/notifier.d.ts +8 -0
- package/dist/services/notifier.js +39 -25
- package/dist/services/oauth.js +5 -7
- package/dist/services/session-memory-sort.d.ts +8 -0
- package/dist/services/session-memory-sort.js +9 -0
- package/dist/services/session-memory.js +8 -9
- package/dist/session/file-history.js +10 -3
- package/dist/session/session-manager.d.ts +23 -1
- package/dist/session/session-manager.js +73 -2
- package/dist/settings/disk-defaults.d.ts +35 -0
- package/dist/settings/disk-defaults.js +24 -0
- package/dist/settings/manager.d.ts +33 -0
- package/dist/settings/manager.js +94 -1
- package/dist/settings/personalization.d.ts +19 -0
- package/dist/settings/personalization.js +7 -0
- package/dist/settings/schema.d.ts +1142 -126
- package/dist/settings/schema.js +119 -10
- package/dist/tool-system/builtin/add-marketplace.d.ts +12 -0
- package/dist/tool-system/builtin/add-marketplace.js +76 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +11 -0
- package/dist/tool-system/builtin/agent-registry.js +8 -4
- package/dist/tool-system/builtin/agent.d.ts +29 -10
- package/dist/tool-system/builtin/agent.js +108 -52
- package/dist/tool-system/builtin/apply-patch/index.js +22 -3
- package/dist/tool-system/builtin/arena.js +6 -7
- package/dist/tool-system/builtin/complete-goal.d.ts +25 -0
- package/dist/tool-system/builtin/complete-goal.js +45 -0
- package/dist/tool-system/builtin/cron.js +53 -9
- package/dist/tool-system/builtin/edit.d.ts +2 -1
- package/dist/tool-system/builtin/edit.js +6 -1
- package/dist/tool-system/builtin/generate-image.d.ts +25 -0
- package/dist/tool-system/builtin/generate-image.js +146 -0
- package/dist/tool-system/builtin/glob.js +7 -0
- package/dist/tool-system/builtin/grep.js +6 -0
- package/dist/tool-system/builtin/index.d.ts +18 -1
- package/dist/tool-system/builtin/index.js +62 -1
- package/dist/tool-system/builtin/notebook-edit.d.ts +2 -1
- package/dist/tool-system/builtin/notebook-edit.js +8 -1
- package/dist/tool-system/builtin/read.d.ts +2 -1
- package/dist/tool-system/builtin/read.js +9 -1
- package/dist/tool-system/builtin/sleep.js +9 -3
- package/dist/tool-system/builtin/task.js +4 -1
- package/dist/tool-system/builtin/update-automation-memory.d.ts +24 -0
- package/dist/tool-system/builtin/update-automation-memory.js +60 -0
- package/dist/tool-system/builtin/view-image.d.ts +18 -0
- package/dist/tool-system/builtin/view-image.js +96 -0
- package/dist/tool-system/builtin/web-search.d.ts +4 -1
- package/dist/tool-system/builtin/web-search.js +36 -3
- package/dist/tool-system/builtin/write.d.ts +2 -1
- package/dist/tool-system/builtin/write.js +7 -1
- package/dist/tool-system/context.d.ts +12 -0
- package/dist/tool-system/executor.d.ts +0 -1
- package/dist/tool-system/executor.js +34 -40
- package/dist/tool-system/investigation-guard.d.ts +4 -1
- package/dist/tool-system/investigation-guard.js +19 -3
- package/dist/tool-system/mcp-manager.d.ts +36 -12
- package/dist/tool-system/mcp-manager.js +173 -10
- package/dist/tool-system/path-policy.d.ts +94 -0
- package/dist/tool-system/path-policy.js +279 -0
- package/dist/tool-system/permission.js +43 -50
- package/dist/tool-system/plan-mode-allowlist.d.ts +21 -0
- package/dist/tool-system/plan-mode-allowlist.js +43 -0
- package/dist/tool-system/registry.js +12 -1
- package/dist/tool-system/validation.d.ts +10 -0
- package/dist/tool-system/validation.js +16 -3
- package/dist/types.d.ts +90 -15
- package/dist/utils/format.js +4 -2
- package/dist/utils/lockfile.js +9 -2
- package/dist/utils/theme.d.ts +6 -0
- package/dist/utils/theme.js +4 -2
- package/package.json +2 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal 5-field cron expression parser + timezone-aware next-trigger
|
|
3
|
+
* calculator. No third-party dependency (core keeps its dep set tight).
|
|
4
|
+
*
|
|
5
|
+
* Fields: minute(0-59) hour(0-23) dayOfMonth(1-31) month(1-12) dayOfWeek(0-6, 0=Sun)
|
|
6
|
+
* Syntax per field: star | star-slash-n | a | a-b | a-b-slash-n | comma-lists of those.
|
|
7
|
+
*
|
|
8
|
+
* Timezone handling uses Intl.DateTimeFormat with a timeZone option to derive
|
|
9
|
+
* the wall-clock parts of a candidate UTC instant in the target zone — correct
|
|
10
|
+
* across DST without a tz library. nextCronTime steps minute-by-minute from the
|
|
11
|
+
* reference and returns the first future instant whose wall-clock parts (in tz)
|
|
12
|
+
* match every field. Bounded to ~2 years so an unsatisfiable expression can't
|
|
13
|
+
* loop forever.
|
|
14
|
+
*/
|
|
15
|
+
export interface ParsedCron {
|
|
16
|
+
minutes: Set<number>;
|
|
17
|
+
hours: Set<number>;
|
|
18
|
+
daysOfMonth: Set<number>;
|
|
19
|
+
months: Set<number>;
|
|
20
|
+
daysOfWeek: Set<number>;
|
|
21
|
+
}
|
|
22
|
+
/** Cheap check: is this string a 5-field cron expression (vs an interval like "5m")? */
|
|
23
|
+
export declare function isCronExpression(s: string): boolean;
|
|
24
|
+
/** Parse a 5-field cron expression into per-field value sets. Throws on invalid input. */
|
|
25
|
+
export declare function parseCronExpression(expr: string): ParsedCron;
|
|
26
|
+
/**
|
|
27
|
+
* Return the next UTC instant (ms) strictly after `fromMs` whose wall-clock
|
|
28
|
+
* time in `timeZone` matches `cron`. Returns null if none within ~2 years
|
|
29
|
+
* (e.g. an impossible expression like Feb 30).
|
|
30
|
+
*/
|
|
31
|
+
export declare function nextCronTime(cron: ParsedCron, timeZone: string, fromMs: number): number | null;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal 5-field cron expression parser + timezone-aware next-trigger
|
|
3
|
+
* calculator. No third-party dependency (core keeps its dep set tight).
|
|
4
|
+
*
|
|
5
|
+
* Fields: minute(0-59) hour(0-23) dayOfMonth(1-31) month(1-12) dayOfWeek(0-6, 0=Sun)
|
|
6
|
+
* Syntax per field: star | star-slash-n | a | a-b | a-b-slash-n | comma-lists of those.
|
|
7
|
+
*
|
|
8
|
+
* Timezone handling uses Intl.DateTimeFormat with a timeZone option to derive
|
|
9
|
+
* the wall-clock parts of a candidate UTC instant in the target zone — correct
|
|
10
|
+
* across DST without a tz library. nextCronTime steps minute-by-minute from the
|
|
11
|
+
* reference and returns the first future instant whose wall-clock parts (in tz)
|
|
12
|
+
* match every field. Bounded to ~2 years so an unsatisfiable expression can't
|
|
13
|
+
* loop forever.
|
|
14
|
+
*/
|
|
15
|
+
const SPECS = [
|
|
16
|
+
{ min: 0, max: 59 }, // minute
|
|
17
|
+
{ min: 0, max: 23 }, // hour
|
|
18
|
+
{ min: 1, max: 31 }, // day of month
|
|
19
|
+
{ min: 1, max: 12 }, // month
|
|
20
|
+
{ min: 0, max: 6 }, // day of week
|
|
21
|
+
];
|
|
22
|
+
/** Cheap check: is this string a 5-field cron expression (vs an interval like "5m")? */
|
|
23
|
+
export function isCronExpression(s) {
|
|
24
|
+
if (typeof s !== "string")
|
|
25
|
+
return false;
|
|
26
|
+
const parts = s.trim().split(/\s+/);
|
|
27
|
+
if (parts.length !== 5)
|
|
28
|
+
return false;
|
|
29
|
+
// Every field must contain only cron field characters.
|
|
30
|
+
return parts.every((p) => /^[\d*/,-]+$/.test(p));
|
|
31
|
+
}
|
|
32
|
+
function parseField(field, spec) {
|
|
33
|
+
const out = new Set();
|
|
34
|
+
for (const part of field.split(",")) {
|
|
35
|
+
// Split optional step: "a-b/n" or "*/n" or "a/n"
|
|
36
|
+
const [rangePart, stepPart] = part.split("/");
|
|
37
|
+
const step = stepPart === undefined ? 1 : parseInt(stepPart, 10);
|
|
38
|
+
if (!Number.isInteger(step) || step <= 0) {
|
|
39
|
+
throw new Error(`Invalid cron step in "${field}"`);
|
|
40
|
+
}
|
|
41
|
+
let lo;
|
|
42
|
+
let hi;
|
|
43
|
+
if (rangePart === "*") {
|
|
44
|
+
lo = spec.min;
|
|
45
|
+
hi = spec.max;
|
|
46
|
+
}
|
|
47
|
+
else if (rangePart.includes("-")) {
|
|
48
|
+
const [a, b] = rangePart.split("-");
|
|
49
|
+
lo = parseInt(a, 10);
|
|
50
|
+
hi = parseInt(b, 10);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
lo = parseInt(rangePart, 10);
|
|
54
|
+
hi = lo;
|
|
55
|
+
}
|
|
56
|
+
if (!Number.isInteger(lo) || !Number.isInteger(hi)) {
|
|
57
|
+
throw new Error(`Invalid cron field "${field}"`);
|
|
58
|
+
}
|
|
59
|
+
if (lo < spec.min || hi > spec.max || lo > hi) {
|
|
60
|
+
throw new Error(`cron field "${field}" out of range [${spec.min}-${spec.max}]`);
|
|
61
|
+
}
|
|
62
|
+
for (let v = lo; v <= hi; v += step)
|
|
63
|
+
out.add(v);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/** Parse a 5-field cron expression into per-field value sets. Throws on invalid input. */
|
|
68
|
+
export function parseCronExpression(expr) {
|
|
69
|
+
const parts = expr.trim().split(/\s+/);
|
|
70
|
+
if (parts.length !== 5) {
|
|
71
|
+
throw new Error(`cron expression must have 5 fields, got ${parts.length}: "${expr}"`);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
minutes: parseField(parts[0], SPECS[0]),
|
|
75
|
+
hours: parseField(parts[1], SPECS[1]),
|
|
76
|
+
daysOfMonth: parseField(parts[2], SPECS[2]),
|
|
77
|
+
months: parseField(parts[3], SPECS[3]),
|
|
78
|
+
daysOfWeek: parseField(parts[4], SPECS[4]),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Cache one formatter per timezone — constructing Intl.DateTimeFormat is costly.
|
|
82
|
+
const formatterCache = new Map();
|
|
83
|
+
function getFormatter(timeZone) {
|
|
84
|
+
let fmt = formatterCache.get(timeZone);
|
|
85
|
+
if (!fmt) {
|
|
86
|
+
fmt = new Intl.DateTimeFormat("en-US", {
|
|
87
|
+
timeZone,
|
|
88
|
+
hour12: false,
|
|
89
|
+
year: "numeric",
|
|
90
|
+
month: "2-digit",
|
|
91
|
+
day: "2-digit",
|
|
92
|
+
hour: "2-digit",
|
|
93
|
+
minute: "2-digit",
|
|
94
|
+
weekday: "short",
|
|
95
|
+
});
|
|
96
|
+
formatterCache.set(timeZone, fmt);
|
|
97
|
+
}
|
|
98
|
+
return fmt;
|
|
99
|
+
}
|
|
100
|
+
const WEEKDAY_INDEX = {
|
|
101
|
+
Sun: 0,
|
|
102
|
+
Mon: 1,
|
|
103
|
+
Tue: 2,
|
|
104
|
+
Wed: 3,
|
|
105
|
+
Thu: 4,
|
|
106
|
+
Fri: 5,
|
|
107
|
+
Sat: 6,
|
|
108
|
+
};
|
|
109
|
+
/** Derive the wall-clock parts of a UTC instant `ms` as seen in `timeZone`. */
|
|
110
|
+
function wallClockInZone(ms, timeZone) {
|
|
111
|
+
const parts = getFormatter(timeZone).formatToParts(new Date(ms));
|
|
112
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
113
|
+
// hour can come back as "24" at midnight in some environments; normalize.
|
|
114
|
+
let hour = parseInt(get("hour"), 10);
|
|
115
|
+
if (hour === 24)
|
|
116
|
+
hour = 0;
|
|
117
|
+
return {
|
|
118
|
+
minute: parseInt(get("minute"), 10),
|
|
119
|
+
hour,
|
|
120
|
+
dayOfMonth: parseInt(get("day"), 10),
|
|
121
|
+
month: parseInt(get("month"), 10),
|
|
122
|
+
dayOfWeek: WEEKDAY_INDEX[get("weekday")] ?? 0,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function matches(cron, wc) {
|
|
126
|
+
return (cron.minutes.has(wc.minute) &&
|
|
127
|
+
cron.hours.has(wc.hour) &&
|
|
128
|
+
cron.daysOfMonth.has(wc.dayOfMonth) &&
|
|
129
|
+
cron.months.has(wc.month) &&
|
|
130
|
+
cron.daysOfWeek.has(wc.dayOfWeek));
|
|
131
|
+
}
|
|
132
|
+
const MINUTE_MS = 60_000;
|
|
133
|
+
// ~2 years of minutes — bounds the search for an unsatisfiable expression.
|
|
134
|
+
const MAX_STEPS = 2 * 366 * 24 * 60;
|
|
135
|
+
/**
|
|
136
|
+
* Return the next UTC instant (ms) strictly after `fromMs` whose wall-clock
|
|
137
|
+
* time in `timeZone` matches `cron`. Returns null if none within ~2 years
|
|
138
|
+
* (e.g. an impossible expression like Feb 30).
|
|
139
|
+
*/
|
|
140
|
+
export function nextCronTime(cron, timeZone, fromMs) {
|
|
141
|
+
// Start at the next whole minute strictly after fromMs (cron has minute
|
|
142
|
+
// granularity; we never return the reference instant itself).
|
|
143
|
+
let candidate = Math.floor(fromMs / MINUTE_MS) * MINUTE_MS + MINUTE_MS;
|
|
144
|
+
for (let i = 0; i < MAX_STEPS; i++) {
|
|
145
|
+
const wc = wallClockInZone(candidate, timeZone);
|
|
146
|
+
if (matches(cron, wc))
|
|
147
|
+
return candidate;
|
|
148
|
+
candidate += MINUTE_MS;
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* automation/ — zero-environment-dependency scheduling module.
|
|
3
|
+
*
|
|
4
|
+
* Hosts (Electron main, future CLI server) load this module and inject their
|
|
5
|
+
* own store + runner. The module imports nothing from Electron/Ink and makes
|
|
6
|
+
* no GUI/TTY assumptions, so the same code runs in any host
|
|
7
|
+
* (docs/automation-plan-2026-05-31.md, D1).
|
|
8
|
+
*/
|
|
9
|
+
import { CronScheduler } from "./scheduler.js";
|
|
10
|
+
import { type CronRunner, type RunSubmitter } from "./runner.js";
|
|
11
|
+
import type { CronStore } from "./store.js";
|
|
12
|
+
export interface StartAutomationDeps {
|
|
13
|
+
/** Persistence backend (injected; module never picks a path itself). */
|
|
14
|
+
store: CronStore;
|
|
15
|
+
/**
|
|
16
|
+
* Execution backend. Provide exactly one:
|
|
17
|
+
* - `runner`: a one-shot run callback (Phase 1 direct-Engine path).
|
|
18
|
+
* - `runManager`: a RunManager submitter (Phase 2 — runs land in RunStore
|
|
19
|
+
* with full history/checkpoint/resume).
|
|
20
|
+
*/
|
|
21
|
+
runner?: CronRunner;
|
|
22
|
+
runManager?: RunSubmitter;
|
|
23
|
+
}
|
|
24
|
+
export interface AutomationHandle {
|
|
25
|
+
scheduler: CronScheduler;
|
|
26
|
+
/** Halt all timers and release the scheduler. Idempotent. */
|
|
27
|
+
stop(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wire a scheduler to a host-provided store + execution backend and restore
|
|
31
|
+
* persisted jobs. Returns a handle the host keeps for its lifetime. Prefers
|
|
32
|
+
* `runManager` when both are supplied (it gives run history).
|
|
33
|
+
*/
|
|
34
|
+
export declare function startAutomation(deps: StartAutomationDeps): AutomationHandle;
|
|
35
|
+
export { CronScheduler, cronScheduler, type CronJob } from "./scheduler.js";
|
|
36
|
+
export { CronStore, defaultCronStorePath } from "./store.js";
|
|
37
|
+
export { bindCronToEngine, bindCronToRunManager, type CronRunner, type CronRunRequest, type CronRunResult, type RunSubmitter, } from "./runner.js";
|
|
38
|
+
export { isCronExpression, parseCronExpression, nextCronTime, type ParsedCron, } from "./cron-expr.js";
|
|
39
|
+
export type { CronPermissionLevel, CreateJobOptions, UpdateJobPatch } from "./scheduler.js";
|
|
40
|
+
export { resolveWritePolicy, wrapUntrustedInput, type WritePolicy, } from "./write-policy.js";
|
|
41
|
+
export { runWriteJobInWorktree, type WriteJobGitOps, type RunWriteJobInput, type RunWriteJobResult, } from "./write-run.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* automation/ — zero-environment-dependency scheduling module.
|
|
3
|
+
*
|
|
4
|
+
* Hosts (Electron main, future CLI server) load this module and inject their
|
|
5
|
+
* own store + runner. The module imports nothing from Electron/Ink and makes
|
|
6
|
+
* no GUI/TTY assumptions, so the same code runs in any host
|
|
7
|
+
* (docs/automation-plan-2026-05-31.md, D1).
|
|
8
|
+
*/
|
|
9
|
+
import { CronScheduler } from "./scheduler.js";
|
|
10
|
+
import { bindCronToEngine, bindCronToRunManager, } from "./runner.js";
|
|
11
|
+
/**
|
|
12
|
+
* Wire a scheduler to a host-provided store + execution backend and restore
|
|
13
|
+
* persisted jobs. Returns a handle the host keeps for its lifetime. Prefers
|
|
14
|
+
* `runManager` when both are supplied (it gives run history).
|
|
15
|
+
*/
|
|
16
|
+
export function startAutomation(deps) {
|
|
17
|
+
const scheduler = new CronScheduler(deps.store);
|
|
18
|
+
if (deps.runManager) {
|
|
19
|
+
bindCronToRunManager(scheduler, deps.runManager);
|
|
20
|
+
}
|
|
21
|
+
else if (deps.runner) {
|
|
22
|
+
bindCronToEngine(scheduler, deps.runner);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
throw new Error("startAutomation requires either a runner or a runManager");
|
|
26
|
+
}
|
|
27
|
+
scheduler.loadJobs();
|
|
28
|
+
return {
|
|
29
|
+
scheduler,
|
|
30
|
+
stop: () => scheduler.stopAll(),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Re-export the building blocks so hosts import everything from one place.
|
|
34
|
+
export { CronScheduler, cronScheduler } from "./scheduler.js";
|
|
35
|
+
export { CronStore, defaultCronStorePath } from "./store.js";
|
|
36
|
+
export { bindCronToEngine, bindCronToRunManager, } from "./runner.js";
|
|
37
|
+
export { isCronExpression, parseCronExpression, nextCronTime, } from "./cron-expr.js";
|
|
38
|
+
export { resolveWritePolicy, wrapUntrustedInput, } from "./write-policy.js";
|
|
39
|
+
export { runWriteJobInWorktree, } from "./write-run.js";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cron-runtime — wire the CronScheduler's executor to a real run backend.
|
|
3
|
+
*
|
|
4
|
+
* B1 fix: `CronScheduler.setExecutor` was never called in production, so cron
|
|
5
|
+
* jobs were created and ticked but did nothing on fire. `bindCronToEngine`
|
|
6
|
+
* installs an executor that, for each fired job, hands a one-shot headless run
|
|
7
|
+
* request to the caller-supplied `runner`.
|
|
8
|
+
*
|
|
9
|
+
* Security contract: cron runs unattended, so each job's permission tier
|
|
10
|
+
* (`job.permissionLevel`) is resolved through `resolveWritePolicy`, which maps
|
|
11
|
+
* the tier to a permissionMode + approval backend (see write-policy.ts). The
|
|
12
|
+
* mode stays "default" so the classifier doesn't add its own acceptEdits
|
|
13
|
+
* auto-allow rules ahead of the backend — the backend is the single source of
|
|
14
|
+
* truth for what a tier permits. An undefined/unknown tier falls back to the
|
|
15
|
+
* read-only backend.
|
|
16
|
+
*/
|
|
17
|
+
import type { CronJob } from "./scheduler.js";
|
|
18
|
+
import type { CronScheduler } from "./scheduler.js";
|
|
19
|
+
import type { PermissionMode } from "../types.js";
|
|
20
|
+
import type { ApprovalBackend } from "../tool-system/permission.js";
|
|
21
|
+
/** What the executor hands to the run backend for one fired job. */
|
|
22
|
+
export interface CronRunRequest {
|
|
23
|
+
job: CronJob;
|
|
24
|
+
/** The prompt to run — `job.prompt`, surfaced for convenience. */
|
|
25
|
+
prompt: string;
|
|
26
|
+
/** Permission mode the run must use (see security contract above). */
|
|
27
|
+
permissionMode: PermissionMode;
|
|
28
|
+
/** Approval backend the run must install (resolved from the job's tier). */
|
|
29
|
+
approvalBackend: ApprovalBackend;
|
|
30
|
+
/** Abort signal for the run — tripped by `CronScheduler.abort(jobId)` when
|
|
31
|
+
* the run must be cancelled mid-flight (e.g. the user deletes its session
|
|
32
|
+
* while it's still executing). Forward to `Engine.run({ signal })`. */
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
}
|
|
35
|
+
export interface CronRunResult {
|
|
36
|
+
text: string;
|
|
37
|
+
reason: string;
|
|
38
|
+
}
|
|
39
|
+
/** The pluggable run backend. Production wires this to a headless Engine run;
|
|
40
|
+
* tests pass a stub. Phase 5 will swap this for a RunManager.submit() path. */
|
|
41
|
+
export type CronRunner = (req: CronRunRequest) => Promise<CronRunResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Install the cron executor. After this call, a fired job invokes `runner`
|
|
44
|
+
* with a run request whose permission tier comes from the job. Errors from
|
|
45
|
+
* `runner` are swallowed by the
|
|
46
|
+
* scheduler's existing try/catch (scheduler.ts) so one bad run never stops
|
|
47
|
+
* future ticks — we still log here so failures are visible.
|
|
48
|
+
*/
|
|
49
|
+
export declare function bindCronToEngine(scheduler: CronScheduler, runner: CronRunner): void;
|
|
50
|
+
/** Minimal structural view of RunManager.submit the executor needs. */
|
|
51
|
+
export interface RunSubmitter {
|
|
52
|
+
submit(input: {
|
|
53
|
+
objective: string;
|
|
54
|
+
cwd?: string;
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
runId: string;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Wire the scheduler to submit each fired job into a RunManager. Records the
|
|
62
|
+
* resulting runId back onto the job (`lastRunId`) so the UI can link a job to
|
|
63
|
+
* its latest run in the RunStore. Read-only is enforced at the RunManager level
|
|
64
|
+
* by the host injecting `approvalBackend: HeadlessApprovalBackend("approve-read-only")`
|
|
65
|
+
* into createRunManager (Phase 2) until sandbox+write tiers land (Phase 4/5).
|
|
66
|
+
*/
|
|
67
|
+
export declare function bindCronToRunManager(scheduler: CronScheduler, runManager: RunSubmitter): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cron-runtime — wire the CronScheduler's executor to a real run backend.
|
|
3
|
+
*
|
|
4
|
+
* B1 fix: `CronScheduler.setExecutor` was never called in production, so cron
|
|
5
|
+
* jobs were created and ticked but did nothing on fire. `bindCronToEngine`
|
|
6
|
+
* installs an executor that, for each fired job, hands a one-shot headless run
|
|
7
|
+
* request to the caller-supplied `runner`.
|
|
8
|
+
*
|
|
9
|
+
* Security contract: cron runs unattended, so each job's permission tier
|
|
10
|
+
* (`job.permissionLevel`) is resolved through `resolveWritePolicy`, which maps
|
|
11
|
+
* the tier to a permissionMode + approval backend (see write-policy.ts). The
|
|
12
|
+
* mode stays "default" so the classifier doesn't add its own acceptEdits
|
|
13
|
+
* auto-allow rules ahead of the backend — the backend is the single source of
|
|
14
|
+
* truth for what a tier permits. An undefined/unknown tier falls back to the
|
|
15
|
+
* read-only backend.
|
|
16
|
+
*/
|
|
17
|
+
import { AUTOMATION_RUN_SOURCE } from "../run/EngineRunner.js";
|
|
18
|
+
import { resolveWritePolicy } from "./write-policy.js";
|
|
19
|
+
/**
|
|
20
|
+
* Install the cron executor. After this call, a fired job invokes `runner`
|
|
21
|
+
* with a run request whose permission tier comes from the job. Errors from
|
|
22
|
+
* `runner` are swallowed by the
|
|
23
|
+
* scheduler's existing try/catch (scheduler.ts) so one bad run never stops
|
|
24
|
+
* future ticks — we still log here so failures are visible.
|
|
25
|
+
*/
|
|
26
|
+
export function bindCronToEngine(scheduler, runner) {
|
|
27
|
+
scheduler.setExecutor(async (job, signal) => {
|
|
28
|
+
const policy = resolveWritePolicy(job.permissionLevel);
|
|
29
|
+
const req = {
|
|
30
|
+
job,
|
|
31
|
+
prompt: job.prompt,
|
|
32
|
+
permissionMode: policy.permissionMode,
|
|
33
|
+
approvalBackend: policy.approvalBackend,
|
|
34
|
+
signal,
|
|
35
|
+
};
|
|
36
|
+
await runner(req);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wire the scheduler to submit each fired job into a RunManager. Records the
|
|
41
|
+
* resulting runId back onto the job (`lastRunId`) so the UI can link a job to
|
|
42
|
+
* its latest run in the RunStore. Read-only is enforced at the RunManager level
|
|
43
|
+
* by the host injecting `approvalBackend: HeadlessApprovalBackend("approve-read-only")`
|
|
44
|
+
* into createRunManager (Phase 2) until sandbox+write tiers land (Phase 4/5).
|
|
45
|
+
*/
|
|
46
|
+
export function bindCronToRunManager(scheduler, runManager) {
|
|
47
|
+
scheduler.setExecutor(async (job, _signal) => {
|
|
48
|
+
const snapshot = await runManager.submit({
|
|
49
|
+
objective: job.prompt,
|
|
50
|
+
cwd: job.cwd,
|
|
51
|
+
metadata: { source: AUTOMATION_RUN_SOURCE, cronJobId: job.id, cronJobName: job.name },
|
|
52
|
+
});
|
|
53
|
+
// Record the run id on the job so the UI can link to run history.
|
|
54
|
+
job.lastRunId = snapshot.runId;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron scheduler — schedule and manage recurring agent tasks.
|
|
3
|
+
*
|
|
4
|
+
* Supports simple cron-like intervals. Each job runs the Engine
|
|
5
|
+
* with a predefined prompt on schedule.
|
|
6
|
+
*/
|
|
7
|
+
import type { CronStore } from "./store.js";
|
|
8
|
+
/** Permission tier a scheduled job runs under (Phase 5 enforces write tiers). */
|
|
9
|
+
export type CronPermissionLevel = "read-only" | "workspace-write" | "full";
|
|
10
|
+
export interface CronJob {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
schedule: string;
|
|
14
|
+
prompt: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
lastRun?: number;
|
|
17
|
+
nextRun?: number;
|
|
18
|
+
runCount: number;
|
|
19
|
+
createdAt: number;
|
|
20
|
+
/** Working directory the job runs in (the project it monitors/edits). */
|
|
21
|
+
cwd?: string;
|
|
22
|
+
/** IANA timezone for cron-expression schedules (e.g. "Asia/Shanghai"). Default "UTC". */
|
|
23
|
+
timezone?: string;
|
|
24
|
+
/** Permission tier; defaults to read-only when unset. */
|
|
25
|
+
permissionLevel?: CronPermissionLevel;
|
|
26
|
+
/** RunStore run id of the most recent execution (Phase 2 RunManager path). */
|
|
27
|
+
lastRunId?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Optional metadata accepted by create(). */
|
|
30
|
+
export interface CreateJobOptions {
|
|
31
|
+
cwd?: string;
|
|
32
|
+
timezone?: string;
|
|
33
|
+
permissionLevel?: CronPermissionLevel;
|
|
34
|
+
}
|
|
35
|
+
/** Fields editable via update(). Any omitted field is left unchanged. */
|
|
36
|
+
export interface UpdateJobPatch {
|
|
37
|
+
name?: string;
|
|
38
|
+
prompt?: string;
|
|
39
|
+
schedule?: string;
|
|
40
|
+
timezone?: string;
|
|
41
|
+
cwd?: string;
|
|
42
|
+
permissionLevel?: CronPermissionLevel;
|
|
43
|
+
}
|
|
44
|
+
export declare class CronScheduler {
|
|
45
|
+
private jobs;
|
|
46
|
+
private timers;
|
|
47
|
+
/** Job ids with an execution currently in flight — prevents a tick from
|
|
48
|
+
* starting a second run of a job whose previous run hasn't finished. */
|
|
49
|
+
private running;
|
|
50
|
+
/** In-flight runs keyed by job id: the AbortController that cancels the run,
|
|
51
|
+
* plus `done` — a promise that resolves when the run has FULLY settled
|
|
52
|
+
* (executor returned, including any post-abort bookkeeping like Engine's
|
|
53
|
+
* final saveState). The re-entrancy guard (`running`) ensures at most one
|
|
54
|
+
* run per job, so one entry per job id is sufficient. `abort(jobId)` trips
|
|
55
|
+
* the controller and returns `done` so callers can wait for the run to
|
|
56
|
+
* actually stop before acting (e.g. deleting its session dir without racing
|
|
57
|
+
* a final write that would recreate it). */
|
|
58
|
+
private runningControllers;
|
|
59
|
+
private nextId;
|
|
60
|
+
private onExecute?;
|
|
61
|
+
/** Optional persistence backend. When set, every create/delete/pause/resume
|
|
62
|
+
* writes the full job set to disk so jobs survive a restart. */
|
|
63
|
+
private store?;
|
|
64
|
+
/** When false, the scheduler persists + tracks jobs but NEVER arms timers
|
|
65
|
+
* (so it can't execute). Used by the desktop agent worker, a separate
|
|
66
|
+
* process from the main process that owns execution. Default true. */
|
|
67
|
+
private executionEnabled;
|
|
68
|
+
constructor(store?: CronStore);
|
|
69
|
+
/**
|
|
70
|
+
* Disable (or re-enable) timer arming / execution. A host that only needs to
|
|
71
|
+
* persist + read jobs — never run them — calls setExecutionEnabled(false).
|
|
72
|
+
* Stops any timers already armed when turning off.
|
|
73
|
+
*/
|
|
74
|
+
setExecutionEnabled(enabled: boolean): void;
|
|
75
|
+
/** Attach (or replace) the persistence backend. Used to give the shared
|
|
76
|
+
* singleton a store at runtime startup without changing its identity. */
|
|
77
|
+
setStore(store: CronStore): void;
|
|
78
|
+
setExecutor(fn: (job: CronJob, signal: AbortSignal) => Promise<void>): void;
|
|
79
|
+
/**
|
|
80
|
+
* Abort the in-flight run of `jobId`, if any. Aborts the AbortSignal handed
|
|
81
|
+
* to the executor (which Engine.run cooperates with — it resolves with
|
|
82
|
+
* reason "aborted_streaming" rather than throwing). Returns false when the
|
|
83
|
+
* job has no run currently in flight (already settled, never started, or
|
|
84
|
+
* unknown id). The run's own finally block clears the controller, so a
|
|
85
|
+
* settled run is a no-op here.
|
|
86
|
+
*/
|
|
87
|
+
abort(jobId: string): Promise<boolean>;
|
|
88
|
+
/**
|
|
89
|
+
* Restore persisted jobs and rebuild their timers. Call once at startup
|
|
90
|
+
* after `setStore`. nextRun is recomputed forward from now — we do NOT
|
|
91
|
+
* catch up on runs missed while the process was down (avoids a restart
|
|
92
|
+
* thundering-herd; aligns with Codex's stateless philosophy). Disabled
|
|
93
|
+
* jobs are restored without a timer.
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* Reconcile in-memory jobs against the on-disk store (the store is the source
|
|
97
|
+
* of truth). Safe to call repeatedly — used both at startup and as a periodic
|
|
98
|
+
* re-sync when another process (e.g. the desktop agent worker) may have
|
|
99
|
+
* created/deleted/changed jobs through the same store. Reconciliation:
|
|
100
|
+
* - jobs on disk but not in memory → added (and armed if enabled)
|
|
101
|
+
* - jobs in memory but not on disk → removed + timer cleared
|
|
102
|
+
* - jobs whose schedule/enabled differ → re-armed to match disk
|
|
103
|
+
*
|
|
104
|
+
* Pass `{ arm: false }` in a host that must NOT execute jobs (the worker —
|
|
105
|
+
* separate process from the one that owns execution); it still tracks +
|
|
106
|
+
* persists but starts no timers, so jobs never run twice across processes.
|
|
107
|
+
*/
|
|
108
|
+
loadJobs(opts?: {
|
|
109
|
+
arm?: boolean;
|
|
110
|
+
}): void;
|
|
111
|
+
private reconcileJobs;
|
|
112
|
+
private nextPersistedId;
|
|
113
|
+
/** Recompute nextRun without arming a timer (for display in disabled/no-arm hosts). */
|
|
114
|
+
private refreshNextRunForDisplay;
|
|
115
|
+
private persist;
|
|
116
|
+
private persistRunStats;
|
|
117
|
+
create(name: string, schedule: string, prompt: string, opts?: CreateJobOptions): CronJob;
|
|
118
|
+
delete(id: string): boolean;
|
|
119
|
+
list(): CronJob[];
|
|
120
|
+
get(id: string): CronJob | undefined;
|
|
121
|
+
pause(id: string): boolean;
|
|
122
|
+
resume(id: string): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Edit an existing job's fields (name/prompt/schedule/timezone/cwd/
|
|
125
|
+
* permissionLevel) without recreating it. A changed schedule is validated up
|
|
126
|
+
* front (throws on invalid, leaving the job untouched), then the timer is
|
|
127
|
+
* re-armed so the new schedule takes effect immediately. Enabled state is
|
|
128
|
+
* preserved — a paused job stays paused (no timer). Returns the updated job,
|
|
129
|
+
* or null if the id is unknown.
|
|
130
|
+
*/
|
|
131
|
+
update(id: string, patch: UpdateJobPatch): CronJob | null;
|
|
132
|
+
stopAll(): void;
|
|
133
|
+
/**
|
|
134
|
+
* Fire a job immediately, out of band of its schedule (the "Run now" button).
|
|
135
|
+
* Respects the re-entrancy guard (no-op if a run is already in flight) and
|
|
136
|
+
* does not disturb the existing timer. Returns false if the id is unknown.
|
|
137
|
+
*/
|
|
138
|
+
runNow(id: string): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Arm a job's timer. Interval schedules ("5m") use setInterval; cron-
|
|
141
|
+
* expression schedules ("0 9 * * 1-5") compute the next trigger in the
|
|
142
|
+
* job's timezone and use setTimeout, re-arming after each fire. nextRun is
|
|
143
|
+
* updated to reflect the scheduled instant.
|
|
144
|
+
*/
|
|
145
|
+
private arm;
|
|
146
|
+
private refreshIntervalNextRun;
|
|
147
|
+
private armCron;
|
|
148
|
+
private clearTimer;
|
|
149
|
+
/**
|
|
150
|
+
* Shared fire path for both schedule kinds. Re-entrancy guard, run-stat
|
|
151
|
+
* bookkeeping, persistence, then the executor. `afterStats` updates nextRun
|
|
152
|
+
* for the next occurrence (interval: now+interval; cron: re-armed inside).
|
|
153
|
+
*/
|
|
154
|
+
private fire;
|
|
155
|
+
}
|
|
156
|
+
export declare const cronScheduler: CronScheduler;
|