microfox 1.1.7 → 1.2.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/cli.mjs CHANGED
@@ -59680,21 +59680,98 @@ function getLatestDeploymentId(cwd, n = 1) {
59680
59680
  const sorted = [...records].sort((a, b) => b.timestamp - a.timestamp);
59681
59681
  return sorted.slice(0, n).map((r) => r.deploymentId);
59682
59682
  }
59683
+ function getDeploymentsPathAtRoot(serverlessRoot) {
59684
+ return path.join(serverlessRoot, DEPLOYMENTS_FILE);
59685
+ }
59686
+ function saveDeploymentRecordToRoot(serverlessRoot, deploymentId, group) {
59687
+ const filePath = getDeploymentsPathAtRoot(serverlessRoot);
59688
+ const records = getDeploymentRecordsFromRoot(serverlessRoot);
59689
+ const newRecord = {
59690
+ deploymentId,
59691
+ timestamp: Date.now(),
59692
+ date: (/* @__PURE__ */ new Date()).toISOString(),
59693
+ ...group != null && group !== "" ? { group } : {}
59694
+ };
59695
+ records.push(newRecord);
59696
+ fs.writeFileSync(filePath, JSON.stringify(records, null, 2));
59697
+ }
59698
+ function getDeploymentRecordsFromRoot(serverlessRoot) {
59699
+ const filePath = getDeploymentsPathAtRoot(serverlessRoot);
59700
+ if (!fs.existsSync(filePath)) {
59701
+ return [];
59702
+ }
59703
+ try {
59704
+ const content = fs.readFileSync(filePath, "utf-8");
59705
+ return JSON.parse(content);
59706
+ } catch (e) {
59707
+ return [];
59708
+ }
59709
+ }
59710
+ function getLatestDeploymentIdFromRoot(serverlessRoot, n = 1, group) {
59711
+ let records = getDeploymentRecordsFromRoot(serverlessRoot);
59712
+ if (group != null && group !== "") {
59713
+ records = records.filter((r) => {
59714
+ var _a;
59715
+ return ((_a = r.group) != null ? _a : "") === group;
59716
+ });
59717
+ }
59718
+ if (records.length === 0) {
59719
+ return [];
59720
+ }
59721
+ const sorted = [...records].sort((a, b) => b.timestamp - a.timestamp);
59722
+ return sorted.slice(0, n).map((r) => r.deploymentId);
59723
+ }
59683
59724
  function findServerlessWorkersDir(startDir) {
59684
59725
  const resolvedStart = path.resolve(startDir);
59726
+ const looksLikeServerlessWorkersDir = (dir2) => {
59727
+ if (!fs.existsSync(dir2)) return false;
59728
+ try {
59729
+ if (!fs.statSync(dir2).isDirectory()) return false;
59730
+ } catch (e) {
59731
+ return false;
59732
+ }
59733
+ if (fs.existsSync(path.join(dir2, "serverless.yml"))) return true;
59734
+ try {
59735
+ const entries = fs.readdirSync(dir2, { withFileTypes: true });
59736
+ for (const e of entries) {
59737
+ if (e.isDirectory() && !e.name.startsWith(".")) {
59738
+ if (fs.existsSync(path.join(dir2, e.name, "serverless.yml"))) {
59739
+ return true;
59740
+ }
59741
+ }
59742
+ }
59743
+ } catch (e) {
59744
+ }
59745
+ return false;
59746
+ };
59685
59747
  const serverlessDirInCurrent = path.join(resolvedStart, DEPLOYMENTS_DIR);
59686
- const configPathInCurrent = path.join(serverlessDirInCurrent, "microfox.json");
59687
- if (fs.existsSync(serverlessDirInCurrent) && fs.existsSync(configPathInCurrent)) {
59748
+ if (looksLikeServerlessWorkersDir(serverlessDirInCurrent)) {
59688
59749
  return serverlessDirInCurrent;
59689
59750
  }
59690
59751
  const parentDir = path.dirname(resolvedStart);
59691
59752
  const serverlessDirInParent = path.join(parentDir, DEPLOYMENTS_DIR);
59692
- const configPathInParent = path.join(serverlessDirInParent, "microfox.json");
59693
- if (fs.existsSync(serverlessDirInParent) && fs.existsSync(configPathInParent)) {
59753
+ if (looksLikeServerlessWorkersDir(serverlessDirInParent)) {
59694
59754
  return serverlessDirInParent;
59695
59755
  }
59696
59756
  return null;
59697
59757
  }
59758
+ function getPerGroupNames(serverlessRoot) {
59759
+ const rootServerlessYml = path.join(serverlessRoot, "serverless.yml");
59760
+ if (fs.existsSync(rootServerlessYml)) {
59761
+ return null;
59762
+ }
59763
+ const entries = fs.readdirSync(serverlessRoot, { withFileTypes: true });
59764
+ const groups = [];
59765
+ for (const e of entries) {
59766
+ if (e.isDirectory() && !e.name.startsWith(".")) {
59767
+ const groupServerlessYml = path.join(serverlessRoot, e.name, "serverless.yml");
59768
+ if (fs.existsSync(groupServerlessYml)) {
59769
+ groups.push(e.name);
59770
+ }
59771
+ }
59772
+ }
59773
+ return groups.length > 0 ? groups : null;
59774
+ }
59698
59775
 
59699
59776
  // src/commands/push.ts
59700
59777
  var FormData3 = require_form_data();
@@ -59761,18 +59838,28 @@ async function createZipArchive(sourceDir, ignorePatterns) {
59761
59838
  await finalizePromise;
59762
59839
  return zipPath;
59763
59840
  }
59764
- async function pushAction() {
59765
- var _a, _b, _c, _d, _e;
59841
+ async function pushAction(groupname, skipGroup) {
59842
+ var _a, _b;
59766
59843
  let cwd = process.cwd();
59767
59844
  const serverlessDir = findServerlessWorkersDir(cwd);
59768
59845
  if (serverlessDir) {
59769
59846
  cwd = serverlessDir;
59770
59847
  process.chdir(cwd);
59771
59848
  }
59772
- const microfoxConfigPath = path2.join(cwd, "microfox.json");
59849
+ let microfoxConfigPath = path2.join(cwd, "microfox.json");
59773
59850
  if (!fs2.existsSync(microfoxConfigPath)) {
59774
- console.error(source_default.red("\u274C Error: `microfox.json` not found in the current directory."));
59775
- console.log(source_default.yellow("This command must be run from the root of an agent project."));
59851
+ const parentConfigPath = path2.join(path2.dirname(cwd), "microfox.json");
59852
+ if (fs2.existsSync(parentConfigPath)) {
59853
+ try {
59854
+ fs2.copyFileSync(parentConfigPath, microfoxConfigPath);
59855
+ } catch (e) {
59856
+ }
59857
+ microfoxConfigPath = fs2.existsSync(microfoxConfigPath) ? microfoxConfigPath : parentConfigPath;
59858
+ }
59859
+ }
59860
+ if (!fs2.existsSync(microfoxConfigPath)) {
59861
+ console.error(source_default.red("\u274C Error: `microfox.json` not found in the current directory or its parent."));
59862
+ console.log(source_default.yellow("Run this command from the root of an agent project, or from its `.serverless-workers` directory."));
59776
59863
  process.exit(1);
59777
59864
  }
59778
59865
  console.log(source_default.cyan("\u{1F680} Pushing your agent to Microfox..."));
@@ -59784,54 +59871,92 @@ async function pushAction() {
59784
59871
  const isV2 = typeof apiVersion === "string" ? apiVersion.toLowerCase() === "v2" : false;
59785
59872
  try {
59786
59873
  if (isV2) {
59787
- const ignorePatterns = ["node_modules/**", ".git/**", ...deploymentConfig.ignorePatterns || microfoxConfig.ignorePatterns || []];
59788
- console.log(source_default.blue("\u{1F4E6} Bundling your agent as a ZIP archive..."));
59789
- const zipPath = await createZipArchive(cwd, ignorePatterns);
59790
- console.log(source_default.blue("\u{1F69A} Uploading archive to Microfox..."));
59791
- const form = new FormData3();
59792
- form.append("archive", fs2.createReadStream(zipPath), {
59793
- filename: "archive.zip",
59794
- contentType: "application/zip"
59795
- });
59796
- if (microfoxConfig.publish) {
59797
- form.append("publish", JSON.stringify(microfoxConfig.publish));
59798
- }
59799
59874
  const projectId = microfoxConfig.projectId || process.env.PROJECT_ID;
59800
59875
  if (!projectId) {
59801
59876
  console.error(source_default.red("\u274C Error: `projectId` is required. Add `projectId` to your microfox.json."));
59802
59877
  process.exit(1);
59803
59878
  }
59804
- const headers = {
59805
- ...form.getHeaders(),
59806
- "x-project-id": projectId
59807
- };
59808
- const response = await axios_default.post(
59809
- API_ENDPOINT_MAPPER({ mode: apiMode, version: "v2", port: apiLocalPort }),
59810
- form,
59811
- {
59812
- headers,
59813
- maxBodyLength: Infinity,
59814
- maxContentLength: Infinity
59879
+ const perGroupNames = getPerGroupNames(cwd);
59880
+ const skipSet = skipGroup ? new Set(skipGroup.split(",").map((g) => g.trim()).filter(Boolean)) : null;
59881
+ let groupsToPush;
59882
+ if (perGroupNames !== null) {
59883
+ groupsToPush = groupname ? perGroupNames.includes(groupname) ? [groupname] : [] : perGroupNames.filter((g) => !(skipSet == null ? void 0 : skipSet.has(g)));
59884
+ if (groupsToPush.length === 0) {
59885
+ if (groupname) {
59886
+ console.error(source_default.red(`\u274C No such group: ${groupname}. Available: ${perGroupNames.join(", ")}`));
59887
+ } else {
59888
+ console.error(source_default.red("\u274C No groups to push (all skipped or none match)."));
59889
+ }
59890
+ process.exit(1);
59815
59891
  }
59816
- );
59817
- if (response.status >= 200 && response.status < 300) {
59818
- console.log(source_default.green("\u2705 Deployment request accepted!"));
59819
- if ((_a = response.data) == null ? void 0 : _a.deploymentId) {
59820
- const deploymentId = response.data.deploymentId;
59821
- console.log(source_default.green(` Deployment ID: ${deploymentId}`));
59822
- saveDeploymentRecord(cwd, deploymentId);
59823
- } else if ((_b = response.data) == null ? void 0 : _b.runId) {
59824
- const runId = response.data.runId;
59825
- console.log(source_default.green(` Run ID: ${runId}`));
59826
- saveDeploymentRecord(cwd, runId);
59892
+ } else {
59893
+ groupsToPush = [];
59894
+ }
59895
+ const ignorePatterns = ["node_modules/**", ".git/**", ...deploymentConfig.ignorePatterns || microfoxConfig.ignorePatterns || []];
59896
+ const serverlessRoot = cwd;
59897
+ const doOnePush = async (archiveCwd, group) => {
59898
+ var _a2, _b2, _c;
59899
+ console.log(source_default.blue(group ? `\u{1F4E6} Bundling group "${group}" as a ZIP archive...` : "\u{1F4E6} Bundling your agent as a ZIP archive..."));
59900
+ const zipPath = await createZipArchive(archiveCwd, ignorePatterns);
59901
+ console.log(source_default.blue(group ? `\u{1F69A} Uploading archive for group "${group}" to Microfox...` : "\u{1F69A} Uploading archive to Microfox..."));
59902
+ const form = new FormData3();
59903
+ form.append("archive", fs2.createReadStream(zipPath), {
59904
+ filename: "archive.zip",
59905
+ contentType: "application/zip"
59906
+ });
59907
+ const publish = microfoxConfig.publish ? { ...microfoxConfig.publish, ...group ? { group } : {} } : group ? { group } : void 0;
59908
+ if (publish) {
59909
+ form.append("publish", JSON.stringify(publish));
59910
+ }
59911
+ const headers = {
59912
+ ...form.getHeaders(),
59913
+ "x-project-id": projectId,
59914
+ ...group ? { "x-deployment-group": group } : {}
59915
+ };
59916
+ const response = await axios_default.post(
59917
+ API_ENDPOINT_MAPPER({ mode: apiMode, version: "v2", port: apiLocalPort }),
59918
+ form,
59919
+ {
59920
+ headers,
59921
+ maxBodyLength: Infinity,
59922
+ maxContentLength: Infinity
59923
+ }
59924
+ );
59925
+ if (response.status >= 200 && response.status < 300) {
59926
+ console.log(source_default.green(group ? `\u2705 Deployment request accepted for group "${group}"!` : "\u2705 Deployment request accepted!"));
59927
+ if ((_a2 = response.data) == null ? void 0 : _a2.deploymentId) {
59928
+ const deploymentId = response.data.deploymentId;
59929
+ console.log(source_default.green(` Deployment ID: ${deploymentId}`));
59930
+ if (group != null && group !== "") {
59931
+ saveDeploymentRecordToRoot(serverlessRoot, deploymentId, group);
59932
+ } else {
59933
+ saveDeploymentRecord(archiveCwd, deploymentId);
59934
+ }
59935
+ } else if ((_b2 = response.data) == null ? void 0 : _b2.runId) {
59936
+ const runId = response.data.runId;
59937
+ console.log(source_default.green(` Run ID: ${runId}`));
59938
+ if (group != null && group !== "") {
59939
+ saveDeploymentRecordToRoot(serverlessRoot, runId, group);
59940
+ } else {
59941
+ saveDeploymentRecord(archiveCwd, runId);
59942
+ }
59943
+ }
59944
+ if ((_c = response.data) == null ? void 0 : _c.message) {
59945
+ console.log(source_default.green(` Message: ${response.data.message}`));
59946
+ }
59947
+ } else {
59948
+ console.error(source_default.red(`\u274C Deployment failed with status: ${response.status}`));
59949
+ console.error(response.data);
59950
+ throw new Error(`Deployment failed: ${response.status}`);
59827
59951
  }
59828
- if ((_c = response.data) == null ? void 0 : _c.message) {
59829
- console.log(source_default.green(` Message: ${response.data.message}`));
59952
+ };
59953
+ if (groupsToPush.length > 0) {
59954
+ for (const group of groupsToPush) {
59955
+ const groupDir = path2.join(cwd, group);
59956
+ await doOnePush(groupDir, group);
59830
59957
  }
59831
59958
  } else {
59832
- console.error(source_default.red(`\u274C Deployment failed with status: ${response.status}`));
59833
- console.error(response.data);
59834
- process.exit(1);
59959
+ await doOnePush(cwd);
59835
59960
  }
59836
59961
  } else {
59837
59962
  let agentApiKey;
@@ -59875,12 +60000,12 @@ async function pushAction() {
59875
60000
  );
59876
60001
  if (response.status >= 200 && response.status < 300) {
59877
60002
  console.log(source_default.green("\u2705 Deployment successful!"));
59878
- if ((_d = response.data) == null ? void 0 : _d.runId) {
60003
+ if ((_a = response.data) == null ? void 0 : _a.runId) {
59879
60004
  const runId = response.data.runId;
59880
60005
  console.log(source_default.green(` Run ID: ${runId}`));
59881
60006
  saveDeploymentRecord(cwd, runId);
59882
60007
  }
59883
- if ((_e = response.data) == null ? void 0 : _e.message) {
60008
+ if ((_b = response.data) == null ? void 0 : _b.message) {
59884
60009
  console.log(source_default.green(` Message: ${response.data.message}`));
59885
60010
  }
59886
60011
  } else {
@@ -59900,9 +60025,9 @@ async function pushAction() {
59900
60025
  process.exit(1);
59901
60026
  }
59902
60027
  }
59903
- var pushCommand = new Command("push").description("Deploy your agent to the Microfox platform").action(async () => {
60028
+ var pushCommand = new Command("push").description("Deploy your agent to the Microfox platform").argument("[groupname]", "Deploy only this group (when using per-group layout, e.g. core, default, workflows)").option("--skip-group <groups>", 'Comma-separated list of groups to skip (e.g. "core,workflows")').action(async (groupname, options = {}) => {
59904
60029
  try {
59905
- await pushAction();
60030
+ await pushAction(groupname, options.skipGroup);
59906
60031
  } catch (error2) {
59907
60032
  console.error(source_default.red("\u274C Error:"), error2 instanceof Error ? error2.message : String(error2));
59908
60033
  process.exit(1);
@@ -59982,7 +60107,7 @@ async function fetchV2Deployment(deploymentId, cfg) {
59982
60107
  return axios_default.get(url2, { headers: { "x-project-id": projectId } });
59983
60108
  }
59984
60109
  async function statusAction(idArg, options) {
59985
- var _a;
60110
+ var _a, _b;
59986
60111
  let cwd = process.cwd();
59987
60112
  const serverlessDir = findServerlessWorkersDir(cwd);
59988
60113
  if (serverlessDir) {
@@ -59993,22 +60118,30 @@ async function statusAction(idArg, options) {
59993
60118
  const apiVersion = deploymentConfig.apiVersion || cfg.apiVersion || cfg.API_VERSION;
59994
60119
  const isV2 = ((_a = apiVersion == null ? void 0 : apiVersion.toLowerCase) == null ? void 0 : _a.call(apiVersion)) === "v2";
59995
60120
  let idsToProcess = [];
60121
+ let latestRecords = null;
59996
60122
  if (idArg === "latest" || !idArg) {
59997
60123
  const n = (options == null ? void 0 : options.number) || 1;
59998
- const latestIds = getLatestDeploymentId(cwd, n);
59999
- if (latestIds.length === 0) {
60124
+ if (serverlessDir) {
60125
+ const records = getDeploymentRecordsFromRoot(serverlessDir);
60126
+ const sorted = [...records].sort((a, b) => b.timestamp - a.timestamp);
60127
+ latestRecords = sorted.slice(0, n);
60128
+ idsToProcess = latestRecords.map((r) => r.deploymentId);
60129
+ } else {
60130
+ idsToProcess = getLatestDeploymentId(cwd, n);
60131
+ }
60132
+ if (idsToProcess.length === 0) {
60000
60133
  console.error(source_default.red("\u274C Error: No deployment records found. Run `npx microfox push` first."));
60001
60134
  process.exit(1);
60002
60135
  }
60003
- idsToProcess = latestIds;
60004
60136
  } else {
60005
60137
  idsToProcess = [idArg];
60006
60138
  }
60007
60139
  if (idsToProcess.length > 1) {
60008
60140
  for (let i = 0; i < idsToProcess.length; i++) {
60009
60141
  const id = idsToProcess[i];
60142
+ const groupLabel = ((_b = latestRecords == null ? void 0 : latestRecords[i]) == null ? void 0 : _b.group) ? ` (group: ${latestRecords[i].group})` : "";
60010
60143
  console.log(source_default.cyan(`
60011
- [${i + 1}/${idsToProcess.length}] Deployment: ${id}`));
60144
+ [${i + 1}/${idsToProcess.length}] Deployment: ${id}${groupLabel}`));
60012
60145
  console.log(source_default.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
60013
60146
  await processSingleStatus(id, cwd, cfg, isV2);
60014
60147
  if (i < idsToProcess.length - 1) {
@@ -60046,6 +60179,9 @@ async function processSingleStatus(idArg, cwd, cfg, isV2) {
60046
60179
  console.log(source_default.gray("----------------------------------------"));
60047
60180
  console.log(`${source_default.bold("Deployment ID:")} ${dep._id || deploymentId}`);
60048
60181
  console.log(`${source_default.bold("Project ID:")} ${dep.projectId || "N/A"}`);
60182
+ if (dep.group != null && dep.group !== "") {
60183
+ console.log(`${source_default.bold("Group:")} ${dep.group}`);
60184
+ }
60049
60185
  console.log(`${source_default.bold("Status:")} ${source_default.green(dep.status)}`);
60050
60186
  if ((_a = dep.error) == null ? void 0 : _a.message) console.log(`${source_default.bold("Error:")} ${dep.error.message}`);
60051
60187
  const start = ((_c = (_b = dep.metrics) == null ? void 0 : _b.timing) == null ? void 0 : _c.startTime) ? new Date(dep.metrics.timing.startTime).toLocaleString() : "N/A";
@@ -60078,7 +60214,7 @@ async function logsAction(idArg, options = {}) {
60078
60214
  let idsToProcess = [];
60079
60215
  if (idArg === "latest" || !idArg) {
60080
60216
  const n = (options == null ? void 0 : options.number) || 1;
60081
- const latestIds = getLatestDeploymentId(cwd, n);
60217
+ const latestIds = serverlessDir ? getLatestDeploymentIdFromRoot(serverlessDir, n) : getLatestDeploymentId(cwd, n);
60082
60218
  if (latestIds.length === 0) {
60083
60219
  console.error(source_default.red("\u274C Error: No deployment records found. Run `npx microfox push` first."));
60084
60220
  process.exit(1);
@@ -61070,7 +61206,7 @@ var kickstartCommand = new Command("kickstart").description("Kickstart a new Mic
61070
61206
  });
61071
61207
 
61072
61208
  // package.json
61073
- var version = "1.1.7";
61209
+ var version = "1.2.0";
61074
61210
 
61075
61211
  // src/commands/track.ts
61076
61212
  var track = new Command("track").description("Run tracker scripts locally.").option("--file <path>", "Run a single tracker file instead of all.").action(async (options) => {