@cfio/cohort-sync 0.2.4 → 0.3.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/dist/index.js +115 -16
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11503,6 +11503,7 @@ var _systemSchema = defineSchema({
|
|
|
11503
11503
|
});
|
|
11504
11504
|
|
|
11505
11505
|
// src/subscription.ts
|
|
11506
|
+
import { execFileSync } from "node:child_process";
|
|
11506
11507
|
function deriveConvexUrl(apiUrl) {
|
|
11507
11508
|
return apiUrl.replace(/\.convex\.site\/?$/, ".convex.cloud");
|
|
11508
11509
|
}
|
|
@@ -11584,6 +11585,7 @@ var markDeliveredByPlugin = makeFunctionReference("notifications:markDeliveredBy
|
|
|
11584
11585
|
var upsertTelemetryFromPlugin = makeFunctionReference("telemetryPlugin:upsertTelemetryFromPlugin");
|
|
11585
11586
|
var upsertSessionsFromPlugin = makeFunctionReference("telemetryPlugin:upsertSessionsFromPlugin");
|
|
11586
11587
|
var pushActivityFromPluginRef = makeFunctionReference("activityFeed:pushActivityFromPlugin");
|
|
11588
|
+
var upsertCronSnapshotFromPluginRef = makeFunctionReference("telemetryPlugin:upsertCronSnapshotFromPlugin");
|
|
11587
11589
|
var getPendingCommandsForPlugin = makeFunctionReference("gatewayCommands:getPendingForPlugin");
|
|
11588
11590
|
var acknowledgeCommandRef = makeFunctionReference("gatewayCommands:acknowledgeCommand");
|
|
11589
11591
|
var addCommentFromPluginRef = makeFunctionReference("comments:addCommentFromPlugin");
|
|
@@ -11740,23 +11742,38 @@ function initCommandSubscription(cfg, logger) {
|
|
|
11740
11742
|
if (processing) return;
|
|
11741
11743
|
if (commands.length === 0) return;
|
|
11742
11744
|
processing = true;
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
11753
|
-
|
|
11754
|
-
|
|
11755
|
-
|
|
11756
|
-
|
|
11745
|
+
try {
|
|
11746
|
+
for (const cmd of commands) {
|
|
11747
|
+
logger.info(`cohort-sync: processing command: ${cmd.type} (${cmd._id})`);
|
|
11748
|
+
try {
|
|
11749
|
+
await c.mutation(acknowledgeCommandRef, {
|
|
11750
|
+
commandId: cmd._id,
|
|
11751
|
+
apiKey: cfg.apiKey
|
|
11752
|
+
});
|
|
11753
|
+
if (cmd.type === "restart") {
|
|
11754
|
+
logger.info("cohort-sync: restart acknowledged, terminating in 500ms");
|
|
11755
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
11756
|
+
process.kill(process.pid, "SIGTERM");
|
|
11757
|
+
return;
|
|
11758
|
+
}
|
|
11759
|
+
if (cmd.type.startsWith("cron") && cmd.payload?.jobId) {
|
|
11760
|
+
handleCronCommand(cmd.type, cmd.payload.jobId, logger);
|
|
11761
|
+
try {
|
|
11762
|
+
const freshJobs = fetchCronJobs(logger);
|
|
11763
|
+
await pushCronSnapshot(cfg.apiKey, freshJobs);
|
|
11764
|
+
} catch (snapErr) {
|
|
11765
|
+
logger.warn(`cohort-sync: post-command snapshot push failed: ${String(snapErr)}`);
|
|
11766
|
+
}
|
|
11767
|
+
} else if (cmd.type.startsWith("cron")) {
|
|
11768
|
+
logger.warn(`cohort-sync: cron command missing jobId: ${cmd.type}`);
|
|
11769
|
+
} else {
|
|
11770
|
+
logger.warn(`cohort-sync: unknown command type: ${cmd.type}`);
|
|
11771
|
+
}
|
|
11772
|
+
} catch (err) {
|
|
11773
|
+
logger.error(`cohort-sync: failed to process command ${cmd._id}: ${String(err)}`);
|
|
11774
|
+
}
|
|
11757
11775
|
}
|
|
11758
|
-
}
|
|
11759
|
-
logger.warn(`cohort-sync: unknown command type: ${cmd.type}`);
|
|
11776
|
+
} finally {
|
|
11760
11777
|
processing = false;
|
|
11761
11778
|
}
|
|
11762
11779
|
},
|
|
@@ -11768,6 +11785,31 @@ function initCommandSubscription(cfg, logger) {
|
|
|
11768
11785
|
getHotState().unsubscribers = [...unsubscribers];
|
|
11769
11786
|
logger.info("cohort-sync: command subscription active");
|
|
11770
11787
|
}
|
|
11788
|
+
function handleCronCommand(type, jobId, logger) {
|
|
11789
|
+
const subcommandMap = {
|
|
11790
|
+
cronEnable: ["cron", "enable", jobId],
|
|
11791
|
+
cronDisable: ["cron", "disable", jobId],
|
|
11792
|
+
cronRunNow: ["cron", "run", jobId],
|
|
11793
|
+
cronDelete: ["cron", "delete", jobId, "--force"]
|
|
11794
|
+
};
|
|
11795
|
+
const args = subcommandMap[type];
|
|
11796
|
+
if (!args) {
|
|
11797
|
+
logger.warn(`cohort-sync: unknown cron command type: ${type}`);
|
|
11798
|
+
return;
|
|
11799
|
+
}
|
|
11800
|
+
const timeout = type === "cronRunNow" ? 3e4 : 15e3;
|
|
11801
|
+
try {
|
|
11802
|
+
execFileSync("openclaw", args, {
|
|
11803
|
+
encoding: "utf8",
|
|
11804
|
+
timeout,
|
|
11805
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
11806
|
+
});
|
|
11807
|
+
logger.info(`cohort-sync: cron command ${type} executed for job ${jobId}`);
|
|
11808
|
+
} catch (err) {
|
|
11809
|
+
logger.error(`cohort-sync: cron command ${type} failed for job ${jobId}: ${String(err)}`);
|
|
11810
|
+
throw err;
|
|
11811
|
+
}
|
|
11812
|
+
}
|
|
11771
11813
|
async function callAddCommentFromPlugin(apiKey, args) {
|
|
11772
11814
|
const c = getOrCreateClient();
|
|
11773
11815
|
if (!c) {
|
|
@@ -11828,6 +11870,15 @@ async function pushActivity(apiKey, entries) {
|
|
|
11828
11870
|
getLogger().error(`cohort-sync: pushActivity failed: ${err}`);
|
|
11829
11871
|
}
|
|
11830
11872
|
}
|
|
11873
|
+
async function pushCronSnapshot(apiKey, jobs) {
|
|
11874
|
+
const c = getOrCreateClient();
|
|
11875
|
+
if (!c) return;
|
|
11876
|
+
try {
|
|
11877
|
+
await c.mutation(upsertCronSnapshotFromPluginRef, { apiKey, jobs });
|
|
11878
|
+
} catch (err) {
|
|
11879
|
+
getLogger().error(`cohort-sync: pushCronSnapshot failed: ${err}`);
|
|
11880
|
+
}
|
|
11881
|
+
}
|
|
11831
11882
|
function saveIntervalsToHot(heartbeat, activityFlush) {
|
|
11832
11883
|
const state = getHotState();
|
|
11833
11884
|
state.intervals = { heartbeat, activityFlush };
|
|
@@ -11891,6 +11942,44 @@ function fetchSkills(logger) {
|
|
|
11891
11942
|
return [];
|
|
11892
11943
|
}
|
|
11893
11944
|
}
|
|
11945
|
+
function fetchCronJobs(logger) {
|
|
11946
|
+
try {
|
|
11947
|
+
const raw = execSync("openclaw cron list --all --json", {
|
|
11948
|
+
encoding: "utf8",
|
|
11949
|
+
timeout: 1e4,
|
|
11950
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
11951
|
+
env: { ...process.env, NO_COLOR: "1" }
|
|
11952
|
+
});
|
|
11953
|
+
const parsed = JSON.parse(extractJson(raw));
|
|
11954
|
+
const list = Array.isArray(parsed) ? parsed : parsed?.jobs ?? [];
|
|
11955
|
+
return list.map((j) => ({
|
|
11956
|
+
id: String(j.jobId ?? j.id ?? "unknown"),
|
|
11957
|
+
text: String(j.name ?? j.text ?? ""),
|
|
11958
|
+
schedule: formatSchedule(j.schedule),
|
|
11959
|
+
...j.nextRunAt != null ? { nextRun: Number(j.nextRunAt) } : {},
|
|
11960
|
+
...j.lastRunAt != null ? { lastRun: Number(j.lastRunAt) } : {},
|
|
11961
|
+
...j.lastStatus ? { lastStatus: String(j.lastStatus) } : {},
|
|
11962
|
+
enabled: j.enabled !== false,
|
|
11963
|
+
...j.agentId != null ? { agentId: String(j.agentId) } : {}
|
|
11964
|
+
}));
|
|
11965
|
+
} catch (err) {
|
|
11966
|
+
logger.warn(`cohort-sync: failed to fetch cron jobs: ${String(err)}`);
|
|
11967
|
+
return [];
|
|
11968
|
+
}
|
|
11969
|
+
}
|
|
11970
|
+
function formatSchedule(schedule) {
|
|
11971
|
+
if (typeof schedule === "string") return schedule;
|
|
11972
|
+
if (schedule && typeof schedule === "object") {
|
|
11973
|
+
const s = schedule;
|
|
11974
|
+
if (s.kind === "cron" && typeof s.expr === "string") return s.expr;
|
|
11975
|
+
if (s.kind === "interval" && typeof s.everyMs === "number") {
|
|
11976
|
+
const mins = Math.floor(Number(s.everyMs) / 6e4);
|
|
11977
|
+
if (mins > 0) return `*/${mins} * * * *`;
|
|
11978
|
+
return `every ${s.everyMs}ms`;
|
|
11979
|
+
}
|
|
11980
|
+
}
|
|
11981
|
+
return String(schedule);
|
|
11982
|
+
}
|
|
11894
11983
|
var VALID_STATUSES = /* @__PURE__ */ new Set(["idle", "working", "waiting"]);
|
|
11895
11984
|
function normalizeStatus(status) {
|
|
11896
11985
|
return VALID_STATUSES.has(status) ? status : "idle";
|
|
@@ -12933,6 +13022,16 @@ Do not attempt to make more comments until ${resetAt}.`
|
|
|
12933
13022
|
}
|
|
12934
13023
|
}
|
|
12935
13024
|
saveSessionsToDisk(tracker);
|
|
13025
|
+
try {
|
|
13026
|
+
const cronJobs2 = fetchCronJobs(logger);
|
|
13027
|
+
const resolvedJobs = cronJobs2.map((job) => ({
|
|
13028
|
+
...job,
|
|
13029
|
+
agentId: job.agentId ? resolveAgentName(job.agentId) : job.agentId
|
|
13030
|
+
}));
|
|
13031
|
+
await pushCronSnapshot(cfg.apiKey, resolvedJobs);
|
|
13032
|
+
} catch (err) {
|
|
13033
|
+
logger.warn(`cohort-sync: heartbeat cron push failed: ${String(err)}`);
|
|
13034
|
+
}
|
|
12936
13035
|
logger.info(`cohort-sync: heartbeat pushed for ${allAgentIds.length} agents`);
|
|
12937
13036
|
}
|
|
12938
13037
|
async function flushActivityBuffer() {
|
package/dist/package.json
CHANGED