patchwork-os 0.2.0-alpha.2 → 0.2.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.bridge.md +6 -0
- package/README.md +13 -2
- package/dist/approvalHttp.d.ts +11 -2
- package/dist/approvalHttp.js +92 -9
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalQueue.d.ts +12 -1
- package/dist/approvalQueue.js +25 -3
- package/dist/approvalQueue.js.map +1 -1
- package/dist/bridge.js +127 -23
- package/dist/bridge.js.map +1 -1
- package/dist/claudeDriver.d.ts +3 -1
- package/dist/claudeDriver.js +48 -0
- package/dist/claudeDriver.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +1 -1
- package/dist/claudeOrchestrator.js +14 -8
- package/dist/claudeOrchestrator.js.map +1 -1
- package/dist/commands/launchd.d.ts +2 -0
- package/dist/commands/launchd.js +94 -0
- package/dist/commands/launchd.js.map +1 -0
- package/dist/config.d.ts +7 -2
- package/dist/config.js +85 -8
- package/dist/config.js.map +1 -1
- package/dist/connectors/github.d.ts +58 -8
- package/dist/connectors/github.js +321 -84
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gmail.d.ts +4 -1
- package/dist/connectors/gmail.js +77 -16
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.d.ts +60 -0
- package/dist/connectors/googleCalendar.js +329 -0
- package/dist/connectors/googleCalendar.js.map +1 -0
- package/dist/connectors/linear.d.ts +117 -0
- package/dist/connectors/linear.js +248 -0
- package/dist/connectors/linear.js.map +1 -0
- package/dist/connectors/mcpClient.d.ts +56 -0
- package/dist/connectors/mcpClient.js +189 -0
- package/dist/connectors/mcpClient.js.map +1 -0
- package/dist/connectors/mcpOAuth.d.ts +83 -0
- package/dist/connectors/mcpOAuth.js +363 -0
- package/dist/connectors/mcpOAuth.js.map +1 -0
- package/dist/connectors/sentry.d.ts +43 -0
- package/dist/connectors/sentry.js +197 -0
- package/dist/connectors/sentry.js.map +1 -0
- package/dist/connectors/slack.d.ts +50 -0
- package/dist/connectors/slack.js +289 -0
- package/dist/connectors/slack.js.map +1 -0
- package/dist/drivers/claude/api.d.ts +11 -0
- package/dist/drivers/claude/api.js +54 -0
- package/dist/drivers/claude/api.js.map +1 -0
- package/dist/drivers/claude/envSanitizer.d.ts +7 -0
- package/dist/drivers/claude/envSanitizer.js +18 -0
- package/dist/drivers/claude/envSanitizer.js.map +1 -0
- package/dist/drivers/claude/streamParser.d.ts +38 -0
- package/dist/drivers/claude/streamParser.js +34 -0
- package/dist/drivers/claude/streamParser.js.map +1 -0
- package/dist/drivers/claude/subprocess.d.ts +19 -0
- package/dist/drivers/claude/subprocess.js +216 -0
- package/dist/drivers/claude/subprocess.js.map +1 -0
- package/dist/drivers/claude/subprocessSettings.d.ts +9 -0
- package/dist/drivers/claude/subprocessSettings.js +55 -0
- package/dist/drivers/claude/subprocessSettings.js.map +1 -0
- package/dist/drivers/gemini/index.d.ts +18 -0
- package/dist/drivers/gemini/index.js +210 -0
- package/dist/drivers/gemini/index.js.map +1 -0
- package/dist/drivers/grok/index.d.ts +11 -0
- package/dist/drivers/grok/index.js +22 -0
- package/dist/drivers/grok/index.js.map +1 -0
- package/dist/drivers/index.d.ts +23 -0
- package/dist/drivers/index.js +31 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/openai/index.d.ts +24 -0
- package/dist/drivers/openai/index.js +110 -0
- package/dist/drivers/openai/index.js.map +1 -0
- package/dist/drivers/types.d.ts +72 -0
- package/dist/drivers/types.js +30 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/index.js +35 -1
- package/dist/index.js.map +1 -1
- package/dist/installGuard.d.ts +25 -0
- package/dist/installGuard.js +48 -0
- package/dist/installGuard.js.map +1 -0
- package/dist/patchworkConfig.d.ts +9 -0
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/recipes/scheduler.d.ts +23 -7
- package/dist/recipes/scheduler.js +135 -41
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/yamlRunner.d.ts +15 -0
- package/dist/recipes/yamlRunner.js +325 -26
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +14 -1
- package/dist/recipesHttp.js +21 -4
- package/dist/recipesHttp.js.map +1 -1
- package/dist/runLog.d.ts +5 -0
- package/dist/runLog.js +51 -1
- package/dist/runLog.js.map +1 -1
- package/dist/server.d.ts +15 -1
- package/dist/server.js +458 -31
- package/dist/server.js.map +1 -1
- package/dist/tools/addLinearComment.d.ts +55 -0
- package/dist/tools/addLinearComment.js +72 -0
- package/dist/tools/addLinearComment.js.map +1 -0
- package/dist/tools/bridgeDoctor.js +2 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/createLinearIssue.d.ts +84 -0
- package/dist/tools/createLinearIssue.js +146 -0
- package/dist/tools/createLinearIssue.js.map +1 -0
- package/dist/tools/ctxGetTaskContext.d.ts +4 -1
- package/dist/tools/ctxGetTaskContext.js +45 -2
- package/dist/tools/ctxGetTaskContext.js.map +1 -1
- package/dist/tools/fetchCalendarEvents.d.ts +94 -0
- package/dist/tools/fetchCalendarEvents.js +97 -0
- package/dist/tools/fetchCalendarEvents.js.map +1 -0
- package/dist/tools/fetchGithubIssue.d.ts +80 -0
- package/dist/tools/fetchGithubIssue.js +84 -0
- package/dist/tools/fetchGithubIssue.js.map +1 -0
- package/dist/tools/fetchGithubPR.d.ts +89 -0
- package/dist/tools/fetchGithubPR.js +96 -0
- package/dist/tools/fetchGithubPR.js.map +1 -0
- package/dist/tools/fetchLinearIssue.d.ts +112 -0
- package/dist/tools/fetchLinearIssue.js +129 -0
- package/dist/tools/fetchLinearIssue.js.map +1 -0
- package/dist/tools/fetchSentryIssue.d.ts +143 -0
- package/dist/tools/fetchSentryIssue.js +150 -0
- package/dist/tools/fetchSentryIssue.js.map +1 -0
- package/dist/tools/fetchSlackProfile.d.ts +43 -0
- package/dist/tools/fetchSlackProfile.js +46 -0
- package/dist/tools/fetchSlackProfile.js.map +1 -0
- package/dist/tools/getConnectorStatus.d.ts +58 -0
- package/dist/tools/getConnectorStatus.js +56 -0
- package/dist/tools/getConnectorStatus.js.map +1 -0
- package/dist/tools/github/index.d.ts +1 -1
- package/dist/tools/github/index.js +1 -1
- package/dist/tools/github/index.js.map +1 -1
- package/dist/tools/github/pr.d.ts +122 -0
- package/dist/tools/github/pr.js +183 -0
- package/dist/tools/github/pr.js.map +1 -1
- package/dist/tools/index.js +27 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/slackListChannels.d.ts +65 -0
- package/dist/tools/slackListChannels.js +70 -0
- package/dist/tools/slackListChannels.js.map +1 -0
- package/dist/tools/slackPostMessage.d.ts +57 -0
- package/dist/tools/slackPostMessage.js +77 -0
- package/dist/tools/slackPostMessage.js.map +1 -0
- package/dist/tools/updateLinearIssue.d.ts +89 -0
- package/dist/tools/updateLinearIssue.js +117 -0
- package/dist/tools/updateLinearIssue.js.map +1 -0
- package/package.json +4 -2
- package/scripts/start-all.sh +56 -19
- package/templates/co.patchwork-os.bridge.plist +34 -0
- package/templates/recipes/ctx-loop-test.yaml +75 -0
- package/templates/recipes/morning-brief-slack.yaml +57 -0
- package/templates/recipes/morning-brief.yaml +21 -5
- package/templates/recipes/sentry-to-linear.yaml +77 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { lstatSync, realpathSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export const PATCHWORK_PACKAGE_NAME = "patchwork-os";
|
|
5
|
+
/**
|
|
6
|
+
* Detects a symlinked global install produced by `npm install -g .` from a
|
|
7
|
+
* workspace checkout.
|
|
8
|
+
*
|
|
9
|
+
* Strategy: ask npm for the global node_modules root, then lstat the
|
|
10
|
+
* patchwork-os slot inside it. If the slot is a symlink, the install is
|
|
11
|
+
* workspace-linked rather than a real copy.
|
|
12
|
+
*
|
|
13
|
+
* We cannot reliably use import.meta.url or process.argv[1] for this check:
|
|
14
|
+
* - import.meta.url is resolved by Node before we read it (real path, not logical)
|
|
15
|
+
* - process.argv[1] points to the bin shim (/opt/homebrew/bin/patchwork-os),
|
|
16
|
+
* not to the package root in node_modules
|
|
17
|
+
*
|
|
18
|
+
* Returns null for normal installs or when the check cannot be performed.
|
|
19
|
+
*/
|
|
20
|
+
export function detectWorkspaceSymlinkInstall() {
|
|
21
|
+
try {
|
|
22
|
+
// Get the global node_modules root from npm.
|
|
23
|
+
const result = spawnSync("npm", ["root", "-g"], {
|
|
24
|
+
encoding: "utf-8",
|
|
25
|
+
timeout: 5000,
|
|
26
|
+
});
|
|
27
|
+
if (result.error || result.status !== 0)
|
|
28
|
+
return null;
|
|
29
|
+
const globalRoot = result.stdout.trim();
|
|
30
|
+
if (!globalRoot)
|
|
31
|
+
return null;
|
|
32
|
+
const logicalRoot = path.join(globalRoot, PATCHWORK_PACKAGE_NAME);
|
|
33
|
+
// Check if the slot is a symlink (not a real directory copy).
|
|
34
|
+
const stat = lstatSync(logicalRoot);
|
|
35
|
+
if (!stat.isSymbolicLink())
|
|
36
|
+
return null;
|
|
37
|
+
const realRoot = realpathSync(logicalRoot);
|
|
38
|
+
return { logicalRoot, realRoot };
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// npm not found, permission error, etc. → safe default.
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Human-readable install fix instructions. */
|
|
46
|
+
export const SYMLINK_INSTALL_FIX = ` Fix: npm pack && npm install -g ${PATCHWORK_PACKAGE_NAME}-*.tgz\n` +
|
|
47
|
+
` Or install from the registry: npm install -g ${PATCHWORK_PACKAGE_NAME}\n`;
|
|
48
|
+
//# sourceMappingURL=installGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installGuard.js","sourceRoot":"","sources":["../src/installGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;AASrD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,6BAA6B;IAC3C,IAAI,CAAC;QACH,6CAA6C;QAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;YAC9C,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAErD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;QAElE,8DAA8D;QAC9D,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YAAE,OAAO,IAAI,CAAC;QAExC,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC3C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,wDAAwD;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAC9B,qCAAqC,sBAAsB,UAAU;IACrE,kDAAkD,sBAAsB,IAAI,CAAC"}
|
|
@@ -21,6 +21,15 @@ export interface PatchworkConfig {
|
|
|
21
21
|
approvalGate?: "off" | "high" | "all";
|
|
22
22
|
/** Absolute path to a managed settings file (admin-controlled, highest rule precedence). */
|
|
23
23
|
managedSettingsPath?: string;
|
|
24
|
+
recipes?: {
|
|
25
|
+
disabled?: string[];
|
|
26
|
+
};
|
|
27
|
+
/** AI driver mode — persisted so dashboard changes survive restart. */
|
|
28
|
+
driver?: "subprocess" | "api" | "openai" | "grok" | "gemini" | "none";
|
|
29
|
+
/** Notification channel config */
|
|
30
|
+
notifications?: {
|
|
31
|
+
slackChannel?: string;
|
|
32
|
+
};
|
|
24
33
|
}
|
|
25
34
|
export declare function defaultConfigPath(): string;
|
|
26
35
|
export declare function loadConfig(path?: string): PatchworkConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patchworkConfig.js","sourceRoot":"","sources":["../src/patchworkConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"patchworkConfig.js","sourceRoot":"","sources":["../src/patchworkConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAoC1C,MAAM,QAAQ,GAAoB;IAChC,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE;QACT,IAAI,EAAE,IAAI;QACV,eAAe,EAAE,CAAC,MAAM,CAAC;QACzB,iBAAiB,EAAE,KAAK;KACzB;IACD,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC;CACrD,CAAC;AAEF,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,iBAAiB,EAAE;IACnD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC9C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA6B,CAAC;IAC3D,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,MAAuB,EACvB,IAAI,GAAG,iBAAiB,EAAE;IAE1B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import cron from "node-cron";
|
|
1
2
|
import type { Logger } from "../logger.js";
|
|
2
3
|
/**
|
|
3
|
-
* RecipeScheduler — runs cron-triggered recipes on a simple interval
|
|
4
|
+
* RecipeScheduler — runs cron-triggered recipes on a simple interval or
|
|
5
|
+
* standard 5-field cron expression.
|
|
4
6
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Supported schedule forms:
|
|
8
|
+
* @every Ns|Nm|Nh — simple interval (setInterval-based)
|
|
9
|
+
* <5-field cron> — standard cron expression (node-cron-based)
|
|
8
10
|
*
|
|
9
11
|
* Scheduler is a pure consumer of the recipes-on-disk contract and an
|
|
10
12
|
* injected enqueue fn, so it's trivial to unit test without the orchestrator.
|
|
@@ -13,15 +15,20 @@ export type SchedulerEnqueue = (opts: {
|
|
|
13
15
|
prompt: string;
|
|
14
16
|
triggerSource: string;
|
|
15
17
|
}) => string;
|
|
18
|
+
export type SchedulerRunYaml = (name: string) => Promise<void>;
|
|
16
19
|
export interface ScheduledRecipe {
|
|
17
20
|
name: string;
|
|
18
21
|
schedule: string;
|
|
19
22
|
intervalMs: number;
|
|
20
23
|
timer: ReturnType<typeof setInterval>;
|
|
24
|
+
/** Present only for cron5-kind recipes. */
|
|
25
|
+
cronJob?: cron.ScheduledTask;
|
|
21
26
|
}
|
|
22
27
|
export interface SchedulerOptions {
|
|
23
28
|
recipesDir: string;
|
|
24
29
|
enqueue: SchedulerEnqueue;
|
|
30
|
+
/** Called for YAML recipes instead of enqueue. */
|
|
31
|
+
runYaml?: SchedulerRunYaml;
|
|
25
32
|
logger?: Logger;
|
|
26
33
|
/** Override for tests — defaults to setInterval. */
|
|
27
34
|
setInterval?: typeof setInterval;
|
|
@@ -36,10 +43,19 @@ export declare class RecipeScheduler {
|
|
|
36
43
|
constructor(opts: SchedulerOptions);
|
|
37
44
|
start(): ScheduledRecipe[];
|
|
38
45
|
stop(): void;
|
|
39
|
-
|
|
46
|
+
restart(): void;
|
|
47
|
+
list(): ReadonlyArray<Omit<ScheduledRecipe, "timer" | "cronJob">>;
|
|
40
48
|
/** Test hook: dispatch a recipe immediately without waiting for the interval. */
|
|
41
49
|
fireForTest(name: string): void;
|
|
42
50
|
private fire;
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
type ParsedSchedule = {
|
|
53
|
+
kind: "interval";
|
|
54
|
+
intervalMs: number;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "cron5";
|
|
57
|
+
expression: string;
|
|
58
|
+
};
|
|
59
|
+
/** Parse @every forms into milliseconds, or detect a 5-field cron expression. Returns null for unsupported schedules. */
|
|
60
|
+
export declare function parseSchedule(schedule: string): ParsedSchedule | null;
|
|
61
|
+
export {};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { readdirSync, readFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import cron from "node-cron";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
import { loadConfig } from "../patchworkConfig.js";
|
|
3
6
|
import { loadRecipePrompt } from "../recipesHttp.js";
|
|
4
7
|
export class RecipeScheduler {
|
|
5
8
|
opts;
|
|
@@ -13,6 +16,17 @@ export class RecipeScheduler {
|
|
|
13
16
|
}
|
|
14
17
|
start() {
|
|
15
18
|
this.stop();
|
|
19
|
+
// Load disabled list from config
|
|
20
|
+
let disabled = new Set();
|
|
21
|
+
try {
|
|
22
|
+
const cfg = loadConfig();
|
|
23
|
+
if (cfg.recipes?.disabled) {
|
|
24
|
+
disabled = new Set(cfg.recipes.disabled);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// non-fatal — proceed with empty disabled set
|
|
29
|
+
}
|
|
16
30
|
let entries;
|
|
17
31
|
try {
|
|
18
32
|
entries = readdirSync(this.opts.recipesDir);
|
|
@@ -21,35 +35,80 @@ export class RecipeScheduler {
|
|
|
21
35
|
return [];
|
|
22
36
|
}
|
|
23
37
|
for (const f of entries) {
|
|
24
|
-
|
|
38
|
+
const isJson = f.endsWith(".json") && !f.endsWith(".permissions.json");
|
|
39
|
+
const isYaml = f.endsWith(".yaml") || f.endsWith(".yml");
|
|
40
|
+
if (!isJson && !isYaml)
|
|
25
41
|
continue;
|
|
26
42
|
const fullPath = path.join(this.opts.recipesDir, f);
|
|
27
43
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
let name;
|
|
45
|
+
let schedule;
|
|
46
|
+
if (isJson) {
|
|
47
|
+
const raw = readFileSync(fullPath, "utf-8");
|
|
48
|
+
const parsed = JSON.parse(raw);
|
|
49
|
+
if (parsed.trigger?.type !== "cron")
|
|
50
|
+
continue;
|
|
51
|
+
if (!parsed.trigger.schedule ||
|
|
52
|
+
typeof parsed.trigger.schedule !== "string")
|
|
53
|
+
continue;
|
|
54
|
+
schedule = parsed.trigger.schedule;
|
|
55
|
+
name = parsed.name ?? path.basename(f, ".json");
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// YAML
|
|
59
|
+
const raw = readFileSync(fullPath, "utf-8");
|
|
60
|
+
const parsed = parseYaml(raw);
|
|
61
|
+
if (parsed.trigger?.type !== "cron")
|
|
62
|
+
continue;
|
|
63
|
+
schedule = parsed.trigger.at ?? parsed.trigger.schedule;
|
|
64
|
+
if (!schedule || typeof schedule !== "string")
|
|
65
|
+
continue;
|
|
66
|
+
name =
|
|
67
|
+
parsed.name ?? path.basename(f, isYaml ? path.extname(f) : ".yaml");
|
|
68
|
+
}
|
|
69
|
+
// Apply disabled filter
|
|
70
|
+
if (disabled.has(name)) {
|
|
71
|
+
this.opts.logger?.info?.(`[scheduler] skipping disabled recipe "${name}"`);
|
|
34
72
|
continue;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
73
|
+
}
|
|
74
|
+
const parsed2 = parseSchedule(schedule);
|
|
75
|
+
if (parsed2 === null) {
|
|
76
|
+
this.opts.logger?.warn?.(`[scheduler] ignoring recipe "${name}" — unsupported schedule "${schedule}" (use @every Ns|Nm|Nh or a 5-field cron expression)`);
|
|
38
77
|
continue;
|
|
39
78
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
timer
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
79
|
+
if (parsed2.kind === "interval") {
|
|
80
|
+
const intervalMs = parsed2.intervalMs;
|
|
81
|
+
const timer = this.setIntervalFn(() => {
|
|
82
|
+
this.fire(name);
|
|
83
|
+
}, intervalMs);
|
|
84
|
+
if (typeof timer === "object" && "unref" in timer)
|
|
85
|
+
timer.unref();
|
|
86
|
+
this.scheduled.push({
|
|
87
|
+
name,
|
|
88
|
+
schedule,
|
|
89
|
+
intervalMs,
|
|
90
|
+
timer,
|
|
91
|
+
});
|
|
92
|
+
this.opts.logger?.info?.(`[scheduler] "${name}" scheduled every ${intervalMs}ms (${schedule})`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// cron5
|
|
96
|
+
const cronJob = cron.schedule(parsed2.expression, () => {
|
|
97
|
+
this.fire(name);
|
|
98
|
+
});
|
|
99
|
+
// Store a sentinel timer so the ScheduledRecipe shape stays stable
|
|
100
|
+
const dummyTimer = this.setIntervalFn(() => { }, 2_147_483_647);
|
|
101
|
+
if (typeof dummyTimer === "object" && "unref" in dummyTimer)
|
|
102
|
+
dummyTimer.unref();
|
|
103
|
+
this.scheduled.push({
|
|
104
|
+
name,
|
|
105
|
+
schedule,
|
|
106
|
+
intervalMs: 0,
|
|
107
|
+
timer: dummyTimer,
|
|
108
|
+
cronJob,
|
|
109
|
+
});
|
|
110
|
+
this.opts.logger?.info?.(`[scheduler] "${name}" scheduled with cron expression "${schedule}"`);
|
|
111
|
+
}
|
|
53
112
|
}
|
|
54
113
|
catch {
|
|
55
114
|
// skip malformed recipe
|
|
@@ -59,18 +118,45 @@ export class RecipeScheduler {
|
|
|
59
118
|
}
|
|
60
119
|
stop() {
|
|
61
120
|
for (const entry of this.scheduled) {
|
|
62
|
-
|
|
121
|
+
if (entry.cronJob) {
|
|
122
|
+
entry.cronJob.stop();
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
this.clearIntervalFn(entry.timer);
|
|
126
|
+
}
|
|
63
127
|
}
|
|
64
128
|
this.scheduled = [];
|
|
65
129
|
}
|
|
130
|
+
restart() {
|
|
131
|
+
this.stop();
|
|
132
|
+
this.start();
|
|
133
|
+
}
|
|
66
134
|
list() {
|
|
67
|
-
return this.scheduled.map(({ timer: _t, ...rest }) => rest);
|
|
135
|
+
return this.scheduled.map(({ timer: _t, cronJob: _c, ...rest }) => rest);
|
|
68
136
|
}
|
|
69
137
|
/** Test hook: dispatch a recipe immediately without waiting for the interval. */
|
|
70
138
|
fireForTest(name) {
|
|
71
139
|
this.fire(name);
|
|
72
140
|
}
|
|
73
141
|
fire(name) {
|
|
142
|
+
// YAML recipe — delegate to runYaml if provided
|
|
143
|
+
const yamlPath = existsSync(path.join(this.opts.recipesDir, `${name}.yaml`))
|
|
144
|
+
? path.join(this.opts.recipesDir, `${name}.yaml`)
|
|
145
|
+
: existsSync(path.join(this.opts.recipesDir, `${name}.yml`))
|
|
146
|
+
? path.join(this.opts.recipesDir, `${name}.yml`)
|
|
147
|
+
: null;
|
|
148
|
+
if (yamlPath) {
|
|
149
|
+
if (!this.opts.runYaml) {
|
|
150
|
+
this.opts.logger?.warn?.(`[scheduler] skipped "${name}" — YAML recipe requires runYaml callback (start bridge with --claude-driver)`);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.opts.runYaml(name).catch((err) => {
|
|
154
|
+
this.opts.logger?.warn?.(`[scheduler] YAML recipe "${name}" failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
155
|
+
});
|
|
156
|
+
this.opts.logger?.info?.(`[scheduler] fired YAML recipe "${name}"`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// JSON recipe — legacy path
|
|
74
160
|
const loaded = loadRecipePrompt(this.opts.recipesDir, name);
|
|
75
161
|
if (!loaded) {
|
|
76
162
|
this.opts.logger?.warn?.(`[scheduler] skipped "${name}" — recipe file disappeared`);
|
|
@@ -88,23 +174,31 @@ export class RecipeScheduler {
|
|
|
88
174
|
}
|
|
89
175
|
}
|
|
90
176
|
}
|
|
91
|
-
/** Parse @every forms into milliseconds. Returns null for unsupported schedules. */
|
|
177
|
+
/** Parse @every forms into milliseconds, or detect a 5-field cron expression. Returns null for unsupported schedules. */
|
|
92
178
|
export function parseSchedule(schedule) {
|
|
93
179
|
const trimmed = schedule.trim();
|
|
180
|
+
// @every Ns|Nm|Nh
|
|
94
181
|
const m = /^@every\s+(\d+)\s*(ms|s|m|h)$/i.exec(trimmed);
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
182
|
+
if (m) {
|
|
183
|
+
const n = Number.parseInt(m[1], 10);
|
|
184
|
+
const unit = m[2]?.toLowerCase();
|
|
185
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
186
|
+
return null;
|
|
187
|
+
const multiplier = unit === "ms"
|
|
188
|
+
? 1
|
|
189
|
+
: unit === "s"
|
|
190
|
+
? 1000
|
|
191
|
+
: unit === "m"
|
|
192
|
+
? 60_000
|
|
193
|
+
: 60 * 60_000;
|
|
194
|
+
return { kind: "interval", intervalMs: n * multiplier };
|
|
195
|
+
}
|
|
196
|
+
// 5-field cron expression (e.g. "0 8 * * 1-5")
|
|
197
|
+
if (/^\S+\s+\S+\s+\S+\s+\S+\s+\S+$/.test(trimmed)) {
|
|
198
|
+
if (cron.validate(trimmed)) {
|
|
199
|
+
return { kind: "cron5", expression: trimmed };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
109
203
|
}
|
|
110
204
|
//# sourceMappingURL=scheduler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/recipes/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/recipes/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -75,12 +75,27 @@ export interface RunnerDeps {
|
|
|
75
75
|
claudeFn?: (prompt: string, model: string) => Promise<string>;
|
|
76
76
|
/** Optional Claude Code CLI caller for agent steps with driver: claude-code. */
|
|
77
77
|
claudeCodeFn?: (prompt: string) => Promise<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Optional provider driver invoker for agent steps with driver: openai|grok|gemini.
|
|
80
|
+
* Dispatches to src/drivers/* under the hood. If not provided, the runner will
|
|
81
|
+
* lazily construct a driver via createDriver() from drivers/index.js.
|
|
82
|
+
*/
|
|
83
|
+
providerDriverFn?: (driverName: "openai" | "grok" | "gemini", prompt: string, model: string | undefined) => Promise<string>;
|
|
84
|
+
}
|
|
85
|
+
export interface StepResult {
|
|
86
|
+
id: string;
|
|
87
|
+
tool?: string;
|
|
88
|
+
status: "ok" | "skipped" | "error";
|
|
89
|
+
error?: string;
|
|
90
|
+
durationMs: number;
|
|
78
91
|
}
|
|
79
92
|
export interface RunResult {
|
|
80
93
|
recipe: string;
|
|
81
94
|
stepsRun: number;
|
|
82
95
|
outputs: string[];
|
|
83
96
|
context: RunContext;
|
|
97
|
+
stepResults: StepResult[];
|
|
98
|
+
errorMessage?: string;
|
|
84
99
|
}
|
|
85
100
|
export declare function loadYamlRecipe(filePath: string): YamlRecipe;
|
|
86
101
|
export declare function validateYamlRecipe(raw: unknown): YamlRecipe;
|