@abtnode/core 1.16.49-beta-20250827-025603-2bb1a7ee → 1.16.49-beta-20250828-094758-93e69d1f

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.
@@ -886,10 +886,65 @@ class DiskBlockletManager extends BaseBlockletManager {
886
886
  throw new Error('No runnable component found');
887
887
  }
888
888
 
889
+ const entryComponentIds = [];
890
+ const nonEntryComponentIds = [];
891
+ let nonEntryComponentRes;
892
+ const componentDidsSet = new Set(componentDids);
893
+ try {
894
+ await forEachBlocklet(
895
+ blocklet1,
896
+ /**
897
+ *
898
+ * @param {import('@blocklet/server-js').BlockletState} b
899
+ * @param {*} param1
900
+ * @returns
901
+ */
902
+ (b) => {
903
+ if (!componentDidsSet.has(b.meta.did)) {
904
+ return;
905
+ }
906
+
907
+ if (b.meta.group === BlockletGroup.gateway) {
908
+ nonEntryComponentIds.push(b.meta.did);
909
+ return;
910
+ }
911
+
912
+ const engine = getBlockletEngine(b.meta);
913
+ if (engine.interpreter === 'blocklet') {
914
+ nonEntryComponentIds.push(b.meta.did);
915
+ return;
916
+ }
917
+
918
+ if (!hasStartEngine(b.meta)) {
919
+ nonEntryComponentIds.push(b.meta.did);
920
+ return;
921
+ }
922
+ entryComponentIds.push(b.meta.did);
923
+ },
924
+ { parallel: true, concurrencyLimit: 4 }
925
+ );
926
+ if (nonEntryComponentIds.length) {
927
+ nonEntryComponentRes = await states.blocklet.setBlockletStatus(did, BlockletStatus.running, {
928
+ componentDids: nonEntryComponentIds,
929
+ operator,
930
+ });
931
+ }
932
+ } catch (err) {
933
+ logger.error('Failed to categorize components into entry and non-entry types', { error: err.message });
934
+ throw err;
935
+ }
936
+
937
+ if (!entryComponentIds.length) {
938
+ return nonEntryComponentRes;
939
+ }
940
+
889
941
  try {
890
942
  // check required config
891
943
  for (const component of blocklet1.children) {
892
- if (!shouldSkipComponent(component.meta.did, componentDids)) {
944
+ if (!entryComponentIds.includes(component.meta.did)) {
945
+ continue;
946
+ }
947
+ if (!shouldSkipComponent(component.meta.did, entryComponentIds)) {
893
948
  const missingProps = getComponentMissingConfigs(component, blocklet1);
894
949
  if (missingProps.length) {
895
950
  throw new Error(
@@ -902,12 +957,18 @@ class DiskBlockletManager extends BaseBlockletManager {
902
957
  }
903
958
 
904
959
  const doc1 = await states.blocklet.setBlockletStatus(did, BlockletStatus.starting, {
905
- componentDids,
960
+ componentDids: entryComponentIds,
906
961
  operator,
907
962
  });
963
+
908
964
  blocklet1.status = BlockletStatus.starting;
909
965
  this.emit(BlockletEvents.statusChange, doc1);
910
- const blocklet = await ensureAppPortsNotOccupied({ blocklet: blocklet1, componentDids, states, manager: this });
966
+ const blocklet = await ensureAppPortsNotOccupied({
967
+ blocklet: blocklet1,
968
+ componentDids: entryComponentIds,
969
+ states,
970
+ manager: this,
971
+ });
911
972
 
912
973
  const nodeInfo = await states.node.read();
913
974
 
@@ -966,7 +1027,7 @@ class DiskBlockletManager extends BaseBlockletManager {
966
1027
  nodeEnvironments,
967
1028
  nodeInfo: await states.node.read(),
968
1029
  e2eMode,
969
- componentDids,
1030
+ componentDids: entryComponentIds,
970
1031
  configSynchronizer: this.configSynchronizer,
971
1032
  });
972
1033
 
@@ -977,7 +1038,7 @@ class DiskBlockletManager extends BaseBlockletManager {
977
1038
  context,
978
1039
  minConsecutiveTime,
979
1040
  timeout: startTimeout,
980
- componentDids,
1041
+ componentDids: entryComponentIds,
981
1042
  };
982
1043
 
983
1044
  if (checkHealthImmediately) {
@@ -988,7 +1049,7 @@ class DiskBlockletManager extends BaseBlockletManager {
988
1049
  entity: 'blocklet',
989
1050
  action: 'check_if_started',
990
1051
  ...params,
991
- id: `${did}/${(componentDids || []).join(',')}`,
1052
+ id: `${did}/${(entryComponentIds || []).join(',')}`,
992
1053
  });
993
1054
  }
994
1055
 
@@ -1002,7 +1063,7 @@ class DiskBlockletManager extends BaseBlockletManager {
1002
1063
 
1003
1064
  const error = Array.isArray(err) ? err[0] : err;
1004
1065
  logger.error('Failed to start blocklet', { error, did, title: blocklet1.meta.title });
1005
- const description = `${getComponentNamesWithVersion(blocklet1, componentDids)} start failed for ${getDisplayName(
1066
+ const description = `${getComponentNamesWithVersion(blocklet1, entryComponentIds)} start failed for ${getDisplayName(
1006
1067
  blocklet1
1007
1068
  )}: ${error.message}`;
1008
1069
  this._createNotification(did, {
@@ -1013,9 +1074,16 @@ class DiskBlockletManager extends BaseBlockletManager {
1013
1074
  severity: 'error',
1014
1075
  });
1015
1076
 
1016
- await this.deleteProcess({ did, componentDids });
1017
- const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, { componentDids, operator });
1018
- this.emit(BlockletEvents.startFailed, { ...res, componentDids, error: { message: error.message } });
1077
+ await this.deleteProcess({ did, componentDids: entryComponentIds });
1078
+ const res = await states.blocklet.setBlockletStatus(did, BlockletStatus.error, {
1079
+ componentDids: entryComponentIds,
1080
+ operator,
1081
+ });
1082
+ this.emit(BlockletEvents.startFailed, {
1083
+ ...res,
1084
+ componentDids: entryComponentIds,
1085
+ error: { message: error.message },
1086
+ });
1019
1087
  this.emit(BlockletEvents.statusChange, { ...res, error: { message: error.message } });
1020
1088
 
1021
1089
  if (throwOnError) {
@@ -3327,9 +3395,11 @@ class DiskBlockletManager extends BaseBlockletManager {
3327
3395
  timeout,
3328
3396
  componentDids,
3329
3397
  enableDocker: nodeInfo.enableDocker,
3398
+ setBlockletRunning: async (componentDid) => {
3399
+ await states.blocklet.setBlockletStatus(did, BlockletStatus.running, { componentDids: [componentDid] });
3400
+ },
3330
3401
  });
3331
3402
 
3332
- // update blocklet status after healthy check
3333
3403
  await states.blocklet.setBlockletStatus(did, BlockletStatus.running, { componentDids });
3334
3404
 
3335
3405
  const res = await this.getBlocklet(did);
@@ -38923,7 +38923,7 @@ module.exports = require("zlib");
38923
38923
  /***/ ((module) => {
38924
38924
 
38925
38925
  "use strict";
38926
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.48","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.48","@abtnode/auth":"1.16.48","@abtnode/certificate-manager":"1.16.48","@abtnode/constant":"1.16.48","@abtnode/cron":"1.16.48","@abtnode/db-cache":"1.16.48","@abtnode/docker-utils":"1.16.48","@abtnode/logger":"1.16.48","@abtnode/models":"1.16.48","@abtnode/queue":"1.16.48","@abtnode/rbac":"1.16.48","@abtnode/router-provider":"1.16.48","@abtnode/static-server":"1.16.48","@abtnode/timemachine":"1.16.48","@abtnode/util":"1.16.48","@aigne/aigne-hub":"^0.6.9","@arcblock/did":"1.22.2","@arcblock/did-connect-js":"1.22.2","@arcblock/did-ext":"1.22.2","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"1.22.2","@arcblock/event-hub":"1.22.2","@arcblock/jwt":"1.22.2","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.22.2","@arcblock/vc":"1.22.2","@blocklet/constant":"1.16.48","@blocklet/did-space-js":"^1.1.18","@blocklet/env":"1.16.48","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.48","@blocklet/resolver":"1.16.48","@blocklet/sdk":"1.16.48","@blocklet/server-js":"1.16.48","@blocklet/store":"1.16.48","@blocklet/theme":"^3.1.30","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.22.2","@ocap/util":"1.22.2","@ocap/wallet":"1.22.2","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","private-ip":"^2.3.4","rate-limiter-flexible":"^5.0.5","read-last-lines":"^1.8.0","semver":"^7.6.3","sequelize":"^6.35.0","shelljs":"^0.8.5","slugify":"^1.6.6","ssri":"^8.0.1","stream-throttle":"^0.1.3","stream-to-promise":"^3.0.0","systeminformation":"^5.23.3","tail":"^2.2.4","tar":"^6.1.11","transliteration":"^2.3.5","ua-parser-js":"^1.0.2","ufo":"^1.5.3","uuid":"^11.1.0","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38926
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@abtnode/core","publishConfig":{"access":"public"},"version":"1.16.48","description":"","main":"lib/index.js","files":["lib"],"scripts":{"lint":"eslint tests lib --ignore-pattern \'tests/assets/*\'","lint:fix":"eslint --fix tests lib","test":"node tools/jest.js","coverage":"npm run test -- --coverage"},"keywords":[],"author":"wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)","license":"Apache-2.0","dependencies":{"@abtnode/analytics":"1.16.48","@abtnode/auth":"1.16.48","@abtnode/certificate-manager":"1.16.48","@abtnode/constant":"1.16.48","@abtnode/cron":"1.16.48","@abtnode/db-cache":"1.16.48","@abtnode/docker-utils":"1.16.48","@abtnode/logger":"1.16.48","@abtnode/models":"1.16.48","@abtnode/queue":"1.16.48","@abtnode/rbac":"1.16.48","@abtnode/router-provider":"1.16.48","@abtnode/static-server":"1.16.48","@abtnode/timemachine":"1.16.48","@abtnode/util":"1.16.48","@aigne/aigne-hub":"^0.6.10","@arcblock/did":"1.22.2","@arcblock/did-connect-js":"1.22.2","@arcblock/did-ext":"1.22.2","@arcblock/did-motif":"^1.1.14","@arcblock/did-util":"1.22.2","@arcblock/event-hub":"1.22.2","@arcblock/jwt":"1.22.2","@arcblock/pm2-events":"^0.0.5","@arcblock/validator":"1.22.2","@arcblock/vc":"1.22.2","@blocklet/constant":"1.16.48","@blocklet/did-space-js":"^1.1.19","@blocklet/env":"1.16.48","@blocklet/error":"^0.2.5","@blocklet/meta":"1.16.48","@blocklet/resolver":"1.16.48","@blocklet/sdk":"1.16.48","@blocklet/server-js":"1.16.48","@blocklet/store":"1.16.48","@blocklet/theme":"^3.1.32","@fidm/x509":"^1.2.1","@ocap/mcrypto":"1.22.2","@ocap/util":"1.22.2","@ocap/wallet":"1.22.2","@slack/webhook":"^5.0.4","archiver":"^7.0.1","axios":"^1.7.9","axon":"^2.0.3","chalk":"^4.1.2","cross-spawn":"^7.0.3","dayjs":"^1.11.13","deep-diff":"^1.0.2","detect-port":"^1.5.1","envfile":"^7.1.0","escape-string-regexp":"^4.0.0","fast-glob":"^3.3.2","filesize":"^10.1.1","flat":"^5.0.2","fs-extra":"^11.2.0","get-port":"^5.1.1","hasha":"^5.2.2","is-base64":"^1.1.0","is-cidr":"4","is-ip":"3","is-url":"^1.2.4","joi":"17.12.2","joi-extension-semver":"^5.0.0","js-yaml":"^4.1.0","kill-port":"^2.0.1","lodash":"^4.17.21","node-stream-zip":"^1.15.0","p-all":"^3.0.0","p-limit":"^3.1.0","p-map":"^4.0.0","p-retry":"^4.6.2","p-wait-for":"^3.2.0","private-ip":"^2.3.4","rate-limiter-flexible":"^5.0.5","read-last-lines":"^1.8.0","semver":"^7.6.3","sequelize":"^6.35.0","shelljs":"^0.8.5","slugify":"^1.6.6","ssri":"^8.0.1","stream-throttle":"^0.1.3","stream-to-promise":"^3.0.0","systeminformation":"^5.23.3","tail":"^2.2.4","tar":"^6.1.11","transliteration":"^2.3.5","ua-parser-js":"^1.0.2","ufo":"^1.5.3","uuid":"^11.1.0","valid-url":"^1.0.9","which":"^2.0.2","xbytes":"^1.8.0"},"devDependencies":{"expand-tilde":"^2.0.2","express":"^4.18.2","jest":"^29.7.0","unzipper":"^0.10.11"},"gitHead":"e5764f753181ed6a7c615cd4fc6682aacf0cb7cd"}');
38927
38927
 
38928
38928
  /***/ }),
38929
38929
 
@@ -48,6 +48,7 @@ const expandSites = (sites = []) => {
48
48
  const domain = typeof domainAlias === 'object' ? domainAlias.value : domainAlias;
49
49
  const tmpSite = cloneDeep(site);
50
50
  delete tmpSite.domainAliases;
51
+ tmpSite.serviceType = isBlockletSite(site.domain) ? 'blocklet' : 'daemon';
51
52
  tmpSite.domain = domain;
52
53
  tmpSite.corsAllowedOrigins = mergeAllowedOrigins(tmpSite.domain, site.corsAllowedOrigins);
53
54
  result.push(tmpSite);
@@ -57,6 +58,7 @@ const expandSites = (sites = []) => {
57
58
 
58
59
  // skip site if domain is BLOCKLET_SITE_GROUP
59
60
  if (!site.domain.endsWith(BLOCKLET_SITE_GROUP_SUFFIX)) {
61
+ site.serviceType = 'daemon';
60
62
  result.push(site);
61
63
  }
62
64
  });
@@ -74,7 +76,6 @@ const expandSites = (sites = []) => {
74
76
  const isDefaultSite = (domain) => DOMAIN_FOR_DEFAULT_SITE === domain;
75
77
 
76
78
  const isIpSite = (domain) => [DOMAIN_FOR_IP_SITE, DOMAIN_FOR_IP_SITE_REGEXP].includes(domain);
77
- // const isIpSite = (domain) => DOMAIN_FOR_IP_SITE === domain;
78
79
 
79
80
  const filterSites = ({ sites, enableDefaultServer, enableIpServer }) => {
80
81
  let result = cloneDeep(sites);
@@ -975,7 +975,10 @@ const validateBlockletChainInfo = (blocklet) => {
975
975
  return chainInfo;
976
976
  };
977
977
 
978
- const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeout, componentDids } = {}) => {
978
+ const checkBlockletProcessHealthy = async (
979
+ blocklet,
980
+ { minConsecutiveTime, timeout, componentDids, setBlockletRunning } = {}
981
+ ) => {
979
982
  await forEachBlocklet(
980
983
  blocklet,
981
984
  async (b) => {
@@ -1002,9 +1005,18 @@ const checkBlockletProcessHealthy = async (blocklet, { minConsecutiveTime, timeo
1002
1005
  const logToTerminal = [blocklet.mode, b.mode].includes(BLOCKLET_MODES.DEVELOPMENT);
1003
1006
 
1004
1007
  const startedAt = Date.now();
1008
+
1005
1009
  // eslint-disable-next-line no-use-before-define
1006
1010
  await _checkProcessHealthy(b, { minConsecutiveTime, timeout, logToTerminal });
1007
1011
  logger.info('done check component healthy', { processId: b.env.processId, time: Date.now() - startedAt });
1012
+
1013
+ if (setBlockletRunning) {
1014
+ try {
1015
+ await setBlockletRunning(b.meta.did);
1016
+ } catch (error) {
1017
+ logger.error(`Failed to set blocklet as running for DID: ${b.meta.name || b.meta.did}`, { error });
1018
+ }
1019
+ }
1008
1020
  },
1009
1021
  { parallel: true }
1010
1022
  );
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.49-beta-20250827-025603-2bb1a7ee",
6
+ "version": "1.16.49-beta-20250828-094758-93e69d1f",
7
7
  "description": "",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -19,22 +19,22 @@
19
19
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
20
20
  "license": "Apache-2.0",
21
21
  "dependencies": {
22
- "@abtnode/analytics": "1.16.49-beta-20250827-025603-2bb1a7ee",
23
- "@abtnode/auth": "1.16.49-beta-20250827-025603-2bb1a7ee",
24
- "@abtnode/certificate-manager": "1.16.49-beta-20250827-025603-2bb1a7ee",
25
- "@abtnode/constant": "1.16.49-beta-20250827-025603-2bb1a7ee",
26
- "@abtnode/cron": "1.16.49-beta-20250827-025603-2bb1a7ee",
27
- "@abtnode/db-cache": "1.16.49-beta-20250827-025603-2bb1a7ee",
28
- "@abtnode/docker-utils": "1.16.49-beta-20250827-025603-2bb1a7ee",
29
- "@abtnode/logger": "1.16.49-beta-20250827-025603-2bb1a7ee",
30
- "@abtnode/models": "1.16.49-beta-20250827-025603-2bb1a7ee",
31
- "@abtnode/queue": "1.16.49-beta-20250827-025603-2bb1a7ee",
32
- "@abtnode/rbac": "1.16.49-beta-20250827-025603-2bb1a7ee",
33
- "@abtnode/router-provider": "1.16.49-beta-20250827-025603-2bb1a7ee",
34
- "@abtnode/static-server": "1.16.49-beta-20250827-025603-2bb1a7ee",
35
- "@abtnode/timemachine": "1.16.49-beta-20250827-025603-2bb1a7ee",
36
- "@abtnode/util": "1.16.49-beta-20250827-025603-2bb1a7ee",
37
- "@aigne/aigne-hub": "^0.6.9",
22
+ "@abtnode/analytics": "1.16.49-beta-20250828-094758-93e69d1f",
23
+ "@abtnode/auth": "1.16.49-beta-20250828-094758-93e69d1f",
24
+ "@abtnode/certificate-manager": "1.16.49-beta-20250828-094758-93e69d1f",
25
+ "@abtnode/constant": "1.16.49-beta-20250828-094758-93e69d1f",
26
+ "@abtnode/cron": "1.16.49-beta-20250828-094758-93e69d1f",
27
+ "@abtnode/db-cache": "1.16.49-beta-20250828-094758-93e69d1f",
28
+ "@abtnode/docker-utils": "1.16.49-beta-20250828-094758-93e69d1f",
29
+ "@abtnode/logger": "1.16.49-beta-20250828-094758-93e69d1f",
30
+ "@abtnode/models": "1.16.49-beta-20250828-094758-93e69d1f",
31
+ "@abtnode/queue": "1.16.49-beta-20250828-094758-93e69d1f",
32
+ "@abtnode/rbac": "1.16.49-beta-20250828-094758-93e69d1f",
33
+ "@abtnode/router-provider": "1.16.49-beta-20250828-094758-93e69d1f",
34
+ "@abtnode/static-server": "1.16.49-beta-20250828-094758-93e69d1f",
35
+ "@abtnode/timemachine": "1.16.49-beta-20250828-094758-93e69d1f",
36
+ "@abtnode/util": "1.16.49-beta-20250828-094758-93e69d1f",
37
+ "@aigne/aigne-hub": "^0.6.10",
38
38
  "@arcblock/did": "1.22.2",
39
39
  "@arcblock/did-connect-js": "1.22.2",
40
40
  "@arcblock/did-ext": "1.22.2",
@@ -45,16 +45,16 @@
45
45
  "@arcblock/pm2-events": "^0.0.5",
46
46
  "@arcblock/validator": "1.22.2",
47
47
  "@arcblock/vc": "1.22.2",
48
- "@blocklet/constant": "1.16.49-beta-20250827-025603-2bb1a7ee",
49
- "@blocklet/did-space-js": "^1.1.18",
50
- "@blocklet/env": "1.16.49-beta-20250827-025603-2bb1a7ee",
48
+ "@blocklet/constant": "1.16.49-beta-20250828-094758-93e69d1f",
49
+ "@blocklet/did-space-js": "^1.1.19",
50
+ "@blocklet/env": "1.16.49-beta-20250828-094758-93e69d1f",
51
51
  "@blocklet/error": "^0.2.5",
52
- "@blocklet/meta": "1.16.49-beta-20250827-025603-2bb1a7ee",
53
- "@blocklet/resolver": "1.16.49-beta-20250827-025603-2bb1a7ee",
54
- "@blocklet/sdk": "1.16.49-beta-20250827-025603-2bb1a7ee",
55
- "@blocklet/server-js": "1.16.49-beta-20250827-025603-2bb1a7ee",
56
- "@blocklet/store": "1.16.49-beta-20250827-025603-2bb1a7ee",
57
- "@blocklet/theme": "^3.1.30",
52
+ "@blocklet/meta": "1.16.49-beta-20250828-094758-93e69d1f",
53
+ "@blocklet/resolver": "1.16.49-beta-20250828-094758-93e69d1f",
54
+ "@blocklet/sdk": "1.16.49-beta-20250828-094758-93e69d1f",
55
+ "@blocklet/server-js": "1.16.49-beta-20250828-094758-93e69d1f",
56
+ "@blocklet/store": "1.16.49-beta-20250828-094758-93e69d1f",
57
+ "@blocklet/theme": "^3.1.32",
58
58
  "@fidm/x509": "^1.2.1",
59
59
  "@ocap/mcrypto": "1.22.2",
60
60
  "@ocap/util": "1.22.2",
@@ -118,5 +118,5 @@
118
118
  "jest": "^29.7.0",
119
119
  "unzipper": "^0.10.11"
120
120
  },
121
- "gitHead": "2b70eea34e8bc8546abb09d38935e8906d9586fd"
121
+ "gitHead": "587711a6df767cafaadbb503daeac586e22c3988"
122
122
  }