@cfio/cohort-sync 0.4.3 → 0.4.5

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 CHANGED
@@ -15,10 +15,10 @@ __export(keychain_exports, {
15
15
  getCredential: () => getCredential,
16
16
  setCredential: () => setCredential
17
17
  });
18
- import { execFile as execFile2 } from "node:child_process";
18
+ import { execFile } from "node:child_process";
19
19
  function securityCmd(args) {
20
20
  return new Promise((resolve, reject) => {
21
- execFile2("security", args, { timeout: 5e3 }, (err, stdout, stderr) => {
21
+ execFile("security", args, { timeout: 5e3 }, (err, stdout, stderr) => {
22
22
  if (err) {
23
23
  reject(Object.assign(err, { stderr }));
24
24
  } else {
@@ -88,8 +88,8 @@ var init_keychain = __esm({
88
88
  });
89
89
 
90
90
  // src/hooks.ts
91
- import fs from "node:fs";
92
- import path from "node:path";
91
+ import fs2 from "node:fs";
92
+ import path2 from "node:path";
93
93
 
94
94
  // ../../node_modules/.pnpm/@sinclair+typebox@0.34.48/node_modules/@sinclair/typebox/build/esm/type/guard/value.mjs
95
95
  var value_exports = {};
@@ -2698,8 +2698,10 @@ __export(type_exports2, {
2698
2698
  var Type = type_exports2;
2699
2699
 
2700
2700
  // src/sync.ts
2701
- import { execFile } from "node:child_process";
2702
- import { promisify } from "node:util";
2701
+ import { execSync } from "node:child_process";
2702
+ import fs from "node:fs";
2703
+ import os from "node:os";
2704
+ import path from "node:path";
2703
2705
 
2704
2706
  // ../../node_modules/.pnpm/convex@1.33.0_patch_hash=l43bztwr6e2lbmpd6ao6hmcg24_react@19.2.1/node_modules/convex/dist/esm/index.js
2705
2707
  var version = "1.33.0";
@@ -4555,12 +4557,12 @@ function createApi(pathParts = []) {
4555
4557
  `API path is expected to be of the form \`api.moduleName.functionName\`. Found: \`${found}\``
4556
4558
  );
4557
4559
  }
4558
- const path2 = pathParts.slice(0, -1).join("/");
4560
+ const path3 = pathParts.slice(0, -1).join("/");
4559
4561
  const exportName = pathParts[pathParts.length - 1];
4560
4562
  if (exportName === "default") {
4561
- return path2;
4563
+ return path3;
4562
4564
  } else {
4563
- return path2 + ":" + exportName;
4565
+ return path3 + ":" + exportName;
4564
4566
  }
4565
4567
  } else if (prop === Symbol.toStringTag) {
4566
4568
  return "FunctionReference";
@@ -7629,16 +7631,16 @@ var require_constants = __commonJS({
7629
7631
  });
7630
7632
  var require_node_gyp_build = __commonJS({
7631
7633
  "../common/temp/node_modules/.pnpm/node-gyp-build@4.8.4/node_modules/node-gyp-build/node-gyp-build.js"(exports, module) {
7632
- var fs2 = __require("fs");
7633
- var path2 = __require("path");
7634
- var os = __require("os");
7634
+ var fs3 = __require("fs");
7635
+ var path3 = __require("path");
7636
+ var os2 = __require("os");
7635
7637
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
7636
7638
  var vars = process.config && process.config.variables || {};
7637
7639
  var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
7638
7640
  var abi = process.versions.modules;
7639
7641
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
7640
- var arch = process.env.npm_config_arch || os.arch();
7641
- var platform = process.env.npm_config_platform || os.platform();
7642
+ var arch = process.env.npm_config_arch || os2.arch();
7643
+ var platform = process.env.npm_config_platform || os2.platform();
7642
7644
  var libc = process.env.LIBC || (isAlpine(platform) ? "musl" : "glibc");
7643
7645
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
7644
7646
  var uv = (process.versions.uv || "").split(".")[0];
@@ -7647,21 +7649,21 @@ var require_node_gyp_build = __commonJS({
7647
7649
  return runtimeRequire(load.resolve(dir));
7648
7650
  }
7649
7651
  load.resolve = load.path = function(dir) {
7650
- dir = path2.resolve(dir || ".");
7652
+ dir = path3.resolve(dir || ".");
7651
7653
  try {
7652
- var name = runtimeRequire(path2.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
7654
+ var name = runtimeRequire(path3.join(dir, "package.json")).name.toUpperCase().replace(/-/g, "_");
7653
7655
  if (process.env[name + "_PREBUILD"]) dir = process.env[name + "_PREBUILD"];
7654
7656
  } catch (err) {
7655
7657
  }
7656
7658
  if (!prebuildsOnly) {
7657
- var release = getFirst(path2.join(dir, "build/Release"), matchBuild);
7659
+ var release = getFirst(path3.join(dir, "build/Release"), matchBuild);
7658
7660
  if (release) return release;
7659
- var debug = getFirst(path2.join(dir, "build/Debug"), matchBuild);
7661
+ var debug = getFirst(path3.join(dir, "build/Debug"), matchBuild);
7660
7662
  if (debug) return debug;
7661
7663
  }
7662
7664
  var prebuild = resolve(dir);
7663
7665
  if (prebuild) return prebuild;
7664
- var nearby = resolve(path2.dirname(process.execPath));
7666
+ var nearby = resolve(path3.dirname(process.execPath));
7665
7667
  if (nearby) return nearby;
7666
7668
  var target = [
7667
7669
  "platform=" + platform,
@@ -7678,26 +7680,26 @@ var require_node_gyp_build = __commonJS({
7678
7680
  ].filter(Boolean).join(" ");
7679
7681
  throw new Error("No native build was found for " + target + "\n loaded from: " + dir + "\n");
7680
7682
  function resolve(dir2) {
7681
- var tuples = readdirSync(path2.join(dir2, "prebuilds")).map(parseTuple);
7683
+ var tuples = readdirSync(path3.join(dir2, "prebuilds")).map(parseTuple);
7682
7684
  var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
7683
7685
  if (!tuple) return;
7684
- var prebuilds = path2.join(dir2, "prebuilds", tuple.name);
7686
+ var prebuilds = path3.join(dir2, "prebuilds", tuple.name);
7685
7687
  var parsed = readdirSync(prebuilds).map(parseTags);
7686
7688
  var candidates = parsed.filter(matchTags(runtime, abi));
7687
7689
  var winner = candidates.sort(compareTags(runtime))[0];
7688
- if (winner) return path2.join(prebuilds, winner.file);
7690
+ if (winner) return path3.join(prebuilds, winner.file);
7689
7691
  }
7690
7692
  };
7691
7693
  function readdirSync(dir) {
7692
7694
  try {
7693
- return fs2.readdirSync(dir);
7695
+ return fs3.readdirSync(dir);
7694
7696
  } catch (err) {
7695
7697
  return [];
7696
7698
  }
7697
7699
  }
7698
7700
  function getFirst(dir, filter) {
7699
7701
  var files = readdirSync(dir).filter(filter);
7700
- return files[0] && path2.join(dir, files[0]);
7702
+ return files[0] && path3.join(dir, files[0]);
7701
7703
  }
7702
7704
  function matchBuild(name) {
7703
7705
  return /\.node$/.test(name);
@@ -7784,7 +7786,7 @@ var require_node_gyp_build = __commonJS({
7784
7786
  return typeof window !== "undefined" && window.process && window.process.type === "renderer";
7785
7787
  }
7786
7788
  function isAlpine(platform2) {
7787
- return platform2 === "linux" && fs2.existsSync("/etc/alpine-release");
7789
+ return platform2 === "linux" && fs3.existsSync("/etc/alpine-release");
7788
7790
  }
7789
7791
  load.parseTags = parseTags;
7790
7792
  load.matchTags = matchTags;
@@ -11760,7 +11762,7 @@ function initCommandSubscription(cfg, logger, resolveAgentName) {
11760
11762
  if (cmd.type.startsWith("cron") && cmd.payload?.jobId) {
11761
11763
  handleCronCommand(cmd.type, cmd.payload.jobId, logger);
11762
11764
  try {
11763
- const freshJobs = await fetchCronJobs(logger);
11765
+ const freshJobs = fetchCronJobs(logger);
11764
11766
  if (freshJobs !== null) {
11765
11767
  const resolvedJobs = resolveAgentName ? freshJobs.map((j) => ({ ...j, agentId: j.agentId ? resolveAgentName(j.agentId) : j.agentId })) : freshJobs;
11766
11768
  await pushCronSnapshot(cfg.apiKey, resolvedJobs);
@@ -11915,7 +11917,6 @@ function getChannelAgent(channelId) {
11915
11917
  }
11916
11918
 
11917
11919
  // src/sync.ts
11918
- var execFileAsync = promisify(execFile);
11919
11920
  function extractJson(raw) {
11920
11921
  const jsonStart = raw.search(/[\[{]/);
11921
11922
  const jsonEndBracket = raw.lastIndexOf("]");
@@ -11926,14 +11927,15 @@ function extractJson(raw) {
11926
11927
  }
11927
11928
  return raw.slice(jsonStart, jsonEnd + 1);
11928
11929
  }
11929
- async function fetchSkills(logger) {
11930
+ function fetchSkills(logger) {
11930
11931
  try {
11931
- const { stdout } = await execFileAsync("openclaw", ["skills", "list", "--json"], {
11932
+ const raw = execSync("openclaw skills list --json", {
11932
11933
  encoding: "utf8",
11933
- timeout: 1e4,
11934
+ timeout: 3e4,
11935
+ stdio: ["ignore", "pipe", "ignore"],
11934
11936
  env: { ...process.env, NO_COLOR: "1" }
11935
11937
  });
11936
- const parsed = JSON.parse(extractJson(stdout));
11938
+ const parsed = JSON.parse(extractJson(raw));
11937
11939
  const list = Array.isArray(parsed) ? parsed : parsed?.skills ?? [];
11938
11940
  return list.map((s) => ({
11939
11941
  name: String(s.name ?? s.id ?? "unknown"),
@@ -11946,27 +11948,29 @@ async function fetchSkills(logger) {
11946
11948
  return [];
11947
11949
  }
11948
11950
  }
11949
- async function fetchCronJobs(logger) {
11951
+ function fetchCronJobs(logger) {
11950
11952
  try {
11951
- const { stdout } = await execFileAsync("openclaw", ["cron", "list", "--all", "--json"], {
11952
- encoding: "utf8",
11953
- timeout: 1e4,
11954
- env: { ...process.env, NO_COLOR: "1" }
11955
- });
11956
- const parsed = JSON.parse(extractJson(stdout));
11957
- const list = Array.isArray(parsed) ? parsed : parsed?.jobs ?? [];
11958
- return list.map((j) => ({
11959
- id: String(j.jobId ?? j.id ?? "unknown"),
11960
- text: String(j.name ?? j.text ?? ""),
11953
+ const storePath = path.join(os.homedir(), ".openclaw", "cron", "jobs.json");
11954
+ logger.info(`cohort-sync: reading cron store from ${storePath} (homedir=${os.homedir()})`);
11955
+ if (!fs.existsSync(storePath)) {
11956
+ logger.warn(`cohort-sync: cron store not found at ${storePath}`);
11957
+ return null;
11958
+ }
11959
+ const raw = fs.readFileSync(storePath, "utf-8");
11960
+ const parsed = JSON.parse(raw);
11961
+ const jobs = Array.isArray(parsed?.jobs) ? parsed.jobs : [];
11962
+ return jobs.map((j) => ({
11963
+ id: String(j.id ?? "unknown"),
11964
+ text: String(j.name ?? ""),
11961
11965
  schedule: formatSchedule(j.schedule),
11962
- ...j.nextRunAt != null ? { nextRun: Number(j.nextRunAt) } : {},
11963
- ...j.lastRunAt != null ? { lastRun: Number(j.lastRunAt) } : {},
11964
- ...j.lastStatus ? { lastStatus: String(j.lastStatus) } : {},
11966
+ ...j.state?.nextRunAtMs != null ? { nextRun: Number(j.state.nextRunAtMs) } : {},
11967
+ ...j.state?.lastRunAtMs != null ? { lastRun: Number(j.state.lastRunAtMs) } : {},
11968
+ ...j.state?.lastStatus ? { lastStatus: String(j.state.lastStatus) } : {},
11965
11969
  enabled: j.enabled !== false,
11966
11970
  ...j.agentId != null ? { agentId: String(j.agentId) } : {}
11967
11971
  }));
11968
11972
  } catch (err) {
11969
- logger.warn(`cohort-sync: failed to fetch cron jobs: ${String(err)}`);
11973
+ logger.warn(`cohort-sync: failed to read cron store: ${String(err)}`);
11970
11974
  return null;
11971
11975
  }
11972
11976
  }
@@ -11987,31 +11991,31 @@ var VALID_STATUSES = /* @__PURE__ */ new Set(["idle", "working", "waiting"]);
11987
11991
  function normalizeStatus(status) {
11988
11992
  return VALID_STATUSES.has(status) ? status : "idle";
11989
11993
  }
11990
- async function v1Get(apiUrl, apiKey, path2) {
11991
- const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path2}`, {
11994
+ async function v1Get(apiUrl, apiKey, path3) {
11995
+ const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path3}`, {
11992
11996
  headers: { Authorization: `Bearer ${apiKey}` },
11993
11997
  signal: AbortSignal.timeout(1e4)
11994
11998
  });
11995
- if (!res.ok) throw new Error(`GET ${path2} \u2192 ${res.status}`);
11999
+ if (!res.ok) throw new Error(`GET ${path3} \u2192 ${res.status}`);
11996
12000
  return res.json();
11997
12001
  }
11998
- async function v1Patch(apiUrl, apiKey, path2, body) {
11999
- const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path2}`, {
12002
+ async function v1Patch(apiUrl, apiKey, path3, body) {
12003
+ const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path3}`, {
12000
12004
  method: "PATCH",
12001
12005
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
12002
12006
  body: JSON.stringify(body),
12003
12007
  signal: AbortSignal.timeout(1e4)
12004
12008
  });
12005
- if (!res.ok) throw new Error(`PATCH ${path2} \u2192 ${res.status}`);
12009
+ if (!res.ok) throw new Error(`PATCH ${path3} \u2192 ${res.status}`);
12006
12010
  }
12007
- async function v1Post(apiUrl, apiKey, path2, body) {
12008
- const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path2}`, {
12011
+ async function v1Post(apiUrl, apiKey, path3, body) {
12012
+ const res = await fetch(`${apiUrl.replace(/\/+$/, "")}${path3}`, {
12009
12013
  method: "POST",
12010
12014
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
12011
12015
  body: JSON.stringify(body),
12012
12016
  signal: AbortSignal.timeout(1e4)
12013
12017
  });
12014
- if (!res.ok) throw new Error(`POST ${path2} \u2192 ${res.status}`);
12018
+ if (!res.ok) throw new Error(`POST ${path3} \u2192 ${res.status}`);
12015
12019
  }
12016
12020
  async function checkForUpdate(currentVersion, logger) {
12017
12021
  try {
@@ -12172,7 +12176,7 @@ async function fullSync(agentName, model, cfg, logger, openClawAgents) {
12172
12176
  } else {
12173
12177
  await syncAgentStatus(agentName, "working", model, cfg, logger);
12174
12178
  }
12175
- const skills = await fetchSkills(logger);
12179
+ const skills = fetchSkills(logger);
12176
12180
  if (skills.length > 0) {
12177
12181
  await syncSkillsToV1(skills, cfg, logger);
12178
12182
  }
@@ -12688,7 +12692,7 @@ function diag(label, data) {
12688
12692
  const line = `[${ts}] ${label}${payload}
12689
12693
  `;
12690
12694
  try {
12691
- fs.appendFileSync(DIAG_LOG_PATH, line);
12695
+ fs2.appendFileSync(DIAG_LOG_PATH, line);
12692
12696
  } catch {
12693
12697
  }
12694
12698
  }
@@ -12716,16 +12720,16 @@ function dumpEvent(event) {
12716
12720
  }
12717
12721
  var PLUGIN_VERSION = "unknown";
12718
12722
  try {
12719
- const pkgPath = path.join(path.dirname(new URL(import.meta.url).pathname), "package.json");
12720
- const pkgJson = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
12723
+ const pkgPath = path2.join(path2.dirname(new URL(import.meta.url).pathname), "package.json");
12724
+ const pkgJson = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
12721
12725
  PLUGIN_VERSION = pkgJson.version ?? "unknown";
12722
12726
  } catch {
12723
12727
  }
12724
12728
  diag("MODULE_LOADED", { BUILD_ID, PLUGIN_VERSION });
12725
12729
  function parseIdentityFile(workspaceDir) {
12726
12730
  try {
12727
- const filePath = path.join(workspaceDir, "IDENTITY.md");
12728
- const content = fs.readFileSync(filePath, "utf-8");
12731
+ const filePath = path2.join(workspaceDir, "IDENTITY.md");
12732
+ const content = fs2.readFileSync(filePath, "utf-8");
12729
12733
  const identity = {};
12730
12734
  for (const line of content.split(/\r?\n/)) {
12731
12735
  const cleaned = line.trim().replace(/^\s*-\s*/, "");
@@ -12763,8 +12767,8 @@ function getOrCreateTracker() {
12763
12767
  state.tracker = fresh;
12764
12768
  return fresh;
12765
12769
  }
12766
- var STATE_FILE_PATH = path.join(
12767
- path.dirname(new URL(import.meta.url).pathname),
12770
+ var STATE_FILE_PATH = path2.join(
12771
+ path2.dirname(new URL(import.meta.url).pathname),
12768
12772
  ".session-state.json"
12769
12773
  );
12770
12774
  function saveSessionsToDisk(tracker) {
@@ -12781,14 +12785,14 @@ function saveSessionsToDisk(tracker) {
12781
12785
  data.sessions.push({ agentName: name, key });
12782
12786
  }
12783
12787
  }
12784
- fs.writeFileSync(STATE_FILE_PATH, JSON.stringify(data));
12788
+ fs2.writeFileSync(STATE_FILE_PATH, JSON.stringify(data));
12785
12789
  } catch {
12786
12790
  }
12787
12791
  }
12788
12792
  function loadSessionsFromDisk(tracker, logger) {
12789
12793
  try {
12790
- if (!fs.existsSync(STATE_FILE_PATH)) return;
12791
- const data = JSON.parse(fs.readFileSync(STATE_FILE_PATH, "utf8"));
12794
+ if (!fs2.existsSync(STATE_FILE_PATH)) return;
12795
+ const data = JSON.parse(fs2.readFileSync(STATE_FILE_PATH, "utf8"));
12792
12796
  if (Date.now() - new Date(data.savedAt).getTime() > 864e5) {
12793
12797
  logger.info("cohort-sync: disk session state too old (>24h), skipping");
12794
12798
  return;
@@ -12846,6 +12850,15 @@ function registerHooks(api, cfg) {
12846
12850
  agentIds: (config?.agents?.list ?? []).map((a) => a.id),
12847
12851
  agentMessageProviders: (config?.agents?.list ?? []).map((a) => ({ id: a.id, mp: a.messageProvider }))
12848
12852
  });
12853
+ diag("CONFIG_DUMP", {
12854
+ configKeys: config ? Object.keys(config) : [],
12855
+ cronKeys: config?.cron ? Object.keys(config.cron) : [],
12856
+ hasCronService: typeof config?.cron?.list === "function",
12857
+ hasCronJobs: !!config?.cron?.jobs,
12858
+ cronStorePath: config?.cron?.storePath ?? null,
12859
+ apiKeys: api ? Object.keys(api).filter((k) => typeof api[k] !== "function") : [],
12860
+ apiMethods: api ? Object.keys(api).filter((k) => typeof api[k] === "function") : []
12861
+ });
12849
12862
  setConvexUrl(cfg);
12850
12863
  setLogger(logger);
12851
12864
  restoreFromHotReload(logger);
@@ -13116,7 +13129,7 @@ Do not attempt to make more comments until ${resetAt}.`
13116
13129
  }
13117
13130
  saveSessionsToDisk(tracker);
13118
13131
  try {
13119
- const cronJobs2 = await fetchCronJobs(logger);
13132
+ const cronJobs2 = fetchCronJobs(logger);
13120
13133
  if (cronJobs2 !== null) {
13121
13134
  const resolvedJobs = cronJobs2.map((job) => ({
13122
13135
  ...job,
@@ -13506,7 +13519,7 @@ Do not attempt to make more comments until ${resetAt}.`
13506
13519
  }
13507
13520
 
13508
13521
  // src/cli.ts
13509
- import { execFile as execFile3 } from "node:child_process";
13522
+ import { execFile as execFile2 } from "node:child_process";
13510
13523
 
13511
13524
  // src/device-auth.ts
13512
13525
  function baseUrl(apiUrl) {
@@ -13587,7 +13600,7 @@ init_keychain();
13587
13600
  function openBrowser(url) {
13588
13601
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
13589
13602
  const args = process.platform === "win32" ? ["/c", "start", url] : [url];
13590
- execFile3(cmd, args, () => {
13603
+ execFile2(cmd, args, () => {
13591
13604
  });
13592
13605
  }
13593
13606
  function registerCohortCli(ctx, cfg) {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Syncs agent status and skills to Cohort dashboard",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfio/cohort-sync",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Syncs agent status and skills to Cohort dashboard",
5
5
  "license": "MIT",
6
6
  "homepage": "https://docs.cohort.bot/gateway",