enigma-memory 0.1.6 → 0.1.8

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.md CHANGED
@@ -21,6 +21,29 @@ Use Enigma as a one-time AI Memory Passport setup: install the package, create t
21
21
  ```sh
22
22
  npm install -g enigma-memory
23
23
  enigma setup --overwrite
24
+ ```
25
+
26
+ `enigma setup --overwrite` is the safe default. It writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON without printing raw memory plaintext. It does not write Claude, Cursor, Kimi, or other third-party app configs.
27
+
28
+ To let setup detect installed or already-configured clients and show the connector plan without mutating client configs:
29
+
30
+ ```sh
31
+ enigma setup --client auto --overwrite
32
+ ```
33
+
34
+ `--client auto` selects clients found by connector detection and falls back to the default setup client list when none are present. The setup output lists which clients were selected, which were skipped, and why.
35
+
36
+ When you are ready to explicitly write connector entries for installed/config-present clients only:
37
+
38
+ ```sh
39
+ enigma setup --connect-installed --overwrite
40
+ ```
41
+
42
+ `--connect-installed` implies auto client selection and is an explicit client-config write flag. It skips missing client configs instead of creating every default client config. Only explicit write flags mutate client configs. Existing explicit connector writes remain available through `enigma connect <client>` without `--dry-run`, and existing `enigma setup --write-connectors` behavior for explicit/default setup clients is unchanged; keep `--dry-run` while reviewing a single planned MCP entry.
43
+
44
+ After setup, use the same local vault from the CLI or connected clients:
45
+
46
+ ```sh
24
47
  enigma remember --text-file ./memory.txt
25
48
  enigma search --query "..."
26
49
  enigma context --query "..." --optimize
@@ -28,9 +51,7 @@ enigma verify --export ./.enigma/export.json
28
51
  enigma connect claude-desktop --dry-run
29
52
  ```
30
53
 
31
- `enigma setup --overwrite` writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON. It does not write Claude, Cursor, Kimi, or other third-party app configs. Client config writes happen only when you explicitly run `enigma connect <client>` without `--dry-run`; keep `--dry-run` while reviewing the planned MCP entry.
32
-
33
- The local Enigma vault remains canonical. Provider-native memory should be treated as a convenience cache only. Enigma receipts prove Enigma-controlled vault state, receipts, checkpoints, and declared boundary operations; they do not prove provider deletion, provider model forgetting, provider-native memory removal, hosted availability, ROI/savings, or compliance certification.
54
+ The local Enigma vault remains canonical. Provider-native memory is non-canonical and should be treated as a convenience cache only. Enigma receipts prove Enigma-controlled vault state, receipts, checkpoints, and declared boundary operations; they do not prove provider deletion, provider model forgetting, provider-native memory removal, hosted availability, ROI/savings, or compliance certification.
34
55
 
35
56
  One-off execution without a global install:
36
57
 
@@ -152,7 +173,9 @@ enigma connect kimi-code --dry-run
152
173
  enigma connect generic-mcp --dry-run
153
174
  ```
154
175
 
155
- Remove `--dry-run` only after you are ready for Enigma to merge the `mcpServers.enigma` entry into that client config. The setup command itself never writes third-party app configs.
176
+ For the one-time setup flow, `enigma setup --client auto --overwrite` reports the installed/config-present clients that connector detection selected and the clients it skipped with reasons. It remains read-only for client configs. `enigma setup --connect-installed --overwrite` is the explicit setup-time write path for installed/config-present clients only; missing configs are skipped rather than created.
177
+
178
+ Remove `--dry-run` from `enigma connect <client>` only after you are ready for Enigma to merge the `mcpServers.enigma` entry into that specific client config. The safe default setup command never writes third-party app configs.
156
179
 
157
180
  Manual MCP entry for Claude Desktop, Cursor, Kimi Code, or any generic MCP client:
158
181
 
@@ -759,17 +759,80 @@ async function initCommand(flags, io) {
759
759
 
760
760
  function setupClientIds(flags) {
761
761
  const raw = getFlag(flags, ['client']);
762
- if (raw === undefined) return [...DEFAULT_SETUP_CLIENTS];
762
+ if (raw === undefined) return { mode: 'default', auto: false, clients: [...DEFAULT_SETUP_CLIENTS], explicit_clients: [] };
763
763
  const values = Array.isArray(raw) ? raw : [raw];
764
764
  const clients = [];
765
+ let auto = false;
765
766
  for (const value of values) {
766
767
  if (value === true || value === '') throw new Error('Missing required --client.');
767
768
  for (const client of String(value).split(',').map((item) => item.trim()).filter(Boolean)) {
769
+ if (client === 'auto') {
770
+ auto = true;
771
+ continue;
772
+ }
768
773
  getClientProfile(client);
769
774
  if (!clients.includes(client)) clients.push(client);
770
775
  }
771
776
  }
772
- return clients.length > 0 ? clients : [...DEFAULT_SETUP_CLIENTS];
777
+ if (auto) return { mode: 'auto', auto: true, clients, explicit_clients: clients };
778
+ return { mode: clients.length > 0 ? 'explicit' : 'default', auto: false, clients: clients.length > 0 ? clients : [...DEFAULT_SETUP_CLIENTS], explicit_clients: clients };
779
+ }
780
+
781
+ function setupDetectedClientReason(client) {
782
+ if (client.installed === true && client.recommended_action === 'already_configured') return 'already_configured';
783
+ if (client.installed === true) return 'installed_needs_repair';
784
+ return 'client_config_present';
785
+ }
786
+
787
+ function setupSkippedClientReason(client) {
788
+ if (client.parse_error === true) return 'config_json_invalid';
789
+ if (client.config_path_exists === false || client.exists === false) return 'client_config_missing';
790
+ if (client.ok === false) return 'config_unreadable';
791
+ return 'not_selected';
792
+ }
793
+
794
+ function publicSetupClientSelectionEntry(client, reason) {
795
+ return {
796
+ client_id: client.client_id,
797
+ display_name: client.display_name,
798
+ reason,
799
+ action: client.recommended_action ?? client.action ?? null,
800
+ installed: client.installed === true,
801
+ config_path_exists: client.config_path_exists === true || client.exists === true,
802
+ };
803
+ }
804
+
805
+ async function setupAutoClientSelection(flags, artifacts, fallbackClients, mode) {
806
+ const doctor = await doctorConnectors({
807
+ ...connectorOptions(flags),
808
+ bundlePath: artifacts.bundlePath,
809
+ redactPaths: true,
810
+ });
811
+ const detected = doctor.clients.filter((client) => (client.config_path_exists === true || client.exists === true) && client.parse_error !== true);
812
+ const fallbackUsed = detected.length === 0;
813
+ const selectedClients = fallbackUsed ? [...fallbackClients] : detected.map((client) => client.client_id);
814
+ const selectedSet = new Set(selectedClients);
815
+ const detectedSet = new Set(detected.map((client) => client.client_id));
816
+ const selected = fallbackUsed
817
+ ? selectedClients.map((clientId) => {
818
+ const client = doctor.clients.find((entry) => entry.client_id === clientId) ?? { client_id: clientId, display_name: getClientProfile(clientId).display_name };
819
+ return publicSetupClientSelectionEntry(client, 'default_fallback_no_client_configs_detected');
820
+ })
821
+ : detected.map((client) => publicSetupClientSelectionEntry(client, setupDetectedClientReason(client)));
822
+ const skipped = doctor.clients
823
+ .filter((client) => !selectedSet.has(client.client_id))
824
+ .map((client) => publicSetupClientSelectionEntry(client, fallbackUsed && !detectedSet.has(client.client_id) ? 'not_in_default_fallback' : setupSkippedClientReason(client)));
825
+ const connectableClientIds = new Set(detected.map((client) => client.client_id));
826
+ return {
827
+ mode,
828
+ auto: true,
829
+ fallback_used: fallbackUsed,
830
+ clients: selectedClients,
831
+ selected,
832
+ skipped,
833
+ connectable_client_ids: connectableClientIds,
834
+ detection: doctor,
835
+ };
773
836
  }
774
837
 
775
838
  function setupMemorySource(flags) {
@@ -915,7 +978,7 @@ function publicConnectPlan(plan, wizard, profile, snippet) {
915
978
  };
916
979
  }
917
980
 
918
- async function setupConnectorPlans(flags, artifacts, clients, writeConnectors, displays) {
981
+ async function setupConnectorPlans(flags, artifacts, clients, writeConnectors, displays, writeClientIds = null) {
919
982
  const publicOptions = {
920
983
  ...connectorOptions(flags),
921
984
  bundlePath: displays.bundle,
@@ -929,9 +992,10 @@ async function setupConnectorPlans(flags, artifacts, clients, writeConnectors, d
929
992
  const profile = getClientProfile(client, publicOptions);
930
993
  const snippet = renderMcpConfig(client, publicOptions);
931
994
  const wizard = planConnectWizard(client, { platform: profile.platform }).clients[0];
932
- const rawPlan = writeConnectors
995
+ const writeAllowed = writeClientIds === null || writeClientIds.has(client);
996
+ const rawPlan = writeConnectors && writeAllowed
933
997
  ? await connectClient(client, { ...writeOptions, dryRun: false })
934
- : { ok: true, changed: true, dryRun: true };
998
+ : { ok: true, changed: !(writeConnectors && !writeAllowed), dryRun: true };
935
999
  const plan = publicConnectPlan(rawPlan, wizard, profile, snippet);
936
1000
  connectors.push({
937
1001
  client_id: client,
@@ -940,19 +1004,33 @@ async function setupConnectorPlans(flags, artifacts, clients, writeConnectors, d
940
1004
  mcp_config_snippet: snippet,
941
1005
  connect_command: `enigma connect ${client} --bundle ${commandPath(displays.bundle)}`,
942
1006
  connect_plan: plan,
1007
+ write_selected: writeAllowed,
1008
+ write_skipped_reason: writeConnectors && !writeAllowed ? 'client_config_missing' : null,
943
1009
  wizard,
944
1010
  });
945
1011
  }
946
1012
  return connectors;
947
1013
  }
948
1014
 
1015
+ function publicSetupClientSelection(selection) {
1016
+ return {
1017
+ mode: selection.mode,
1018
+ auto: selection.auto === true,
1019
+ fallback_used: selection.fallback_used === true,
1020
+ selected: selection.selected,
1021
+ skipped: selection.skipped,
1022
+ };
1023
+ }
1024
+
949
1025
  export async function setupCommand(flags, io) {
950
1026
  const bundleInput = pathFlag(flags, ['bundle', 'file'], DEFAULT_BUNDLE);
951
1027
  const outDirInput = pathFlag(flags, ['out-dir', 'outDir'], dirname(bundleInput));
952
- const clients = setupClientIds(flags);
1028
+ const requestedSelection = setupClientIds(flags);
953
1029
  const overwrite = booleanFlag(flags, ['overwrite'], false);
954
1030
  const dryRun = booleanFlag(flags, ['dry-run', 'dryRun'], false);
955
- const writeConnectors = booleanFlag(flags, ['write-connectors', 'writeConnectors'], false) && !dryRun;
1031
+ const writeConnectorsFlag = booleanFlag(flags, ['write-connectors', 'writeConnectors'], false);
1032
+ const connectInstalled = booleanFlag(flags, ['connect-installed', 'connectInstalled'], false);
1033
+ const connectorWritesRequested = (writeConnectorsFlag || connectInstalled) && !dryRun;
956
1034
  const displays = setupPublicDisplays(bundleInput, outDirInput);
957
1035
  const rawDisplays = setupRawDisplays(bundleInput, outDirInput);
958
1036
  let artifacts;
@@ -961,9 +1039,24 @@ export async function setupCommand(flags, io) {
961
1039
  } catch (error) {
962
1040
  throw publicSetupError(error, rawDisplays, displays);
963
1041
  }
964
- const connectors = await setupConnectorPlans(flags, artifacts, clients, writeConnectors, displays);
1042
+ const selection = connectInstalled || requestedSelection.auto
1043
+ ? await setupAutoClientSelection(flags, artifacts, DEFAULT_SETUP_CLIENTS, connectInstalled ? 'connect_installed' : 'auto')
1044
+ : {
1045
+ ...requestedSelection,
1046
+ fallback_used: false,
1047
+ selected: requestedSelection.clients.map((clientId) => {
1048
+ const profile = getClientProfile(clientId);
1049
+ return publicSetupClientSelectionEntry({ client_id: clientId, display_name: profile.display_name }, requestedSelection.mode === 'default' ? 'default_setup_client' : 'explicit_client');
1050
+ }),
1051
+ skipped: [],
1052
+ connectable_client_ids: null,
1053
+ };
1054
+ const clients = selection.clients;
1055
+ const writeClientIds = connectInstalled ? selection.connectable_client_ids : null;
1056
+ const connectors = await setupConnectorPlans(flags, artifacts, clients, connectorWritesRequested, displays, writeClientIds);
965
1057
  const doctor = await setupDoctorChecks(flags, artifacts, clients, displays);
966
1058
  const ok = artifacts.verifyReport.ok === true;
1059
+ const anyConnectorWritePerformed = connectors.some((connector) => connector.connect_plan.writes_performed === true);
967
1060
 
968
1061
  print({
969
1062
  ok,
@@ -971,7 +1064,10 @@ export async function setupCommand(flags, io) {
971
1064
  command: 'enigma setup',
972
1065
  dry_run: dryRun,
973
1066
  artifacts_written: !dryRun,
974
- client_configs_written: writeConnectors,
1067
+ client_configs_written: writeConnectorsFlag && !dryRun ? true : anyConnectorWritePerformed,
1068
+ client_config_write_requested: connectorWritesRequested,
1069
+ connector_write_mode: connectInstalled ? 'installed_only' : (writeConnectorsFlag ? 'selected_clients' : 'plan_only'),
1070
+ connect_installed: connectInstalled,
975
1071
  bundle: displays.bundle,
976
1072
  context_pack: displays.context_pack,
977
1073
  export: displays.export,
@@ -985,10 +1081,19 @@ export async function setupCommand(flags, io) {
985
1081
  provider_credentials_required: false,
986
1082
  provider_native_memory_canonical: false,
987
1083
  selected_clients: clients,
1084
+ skipped_clients: selection.skipped,
1085
+ client_selection: publicSetupClientSelection(selection),
1086
+ connector_write_skips: connectors
1087
+ .filter((connector) => connector.write_skipped_reason)
1088
+ .map((connector) => ({
1089
+ client_id: connector.client_id,
1090
+ display_name: connector.display_name,
1091
+ reason: connector.write_skipped_reason,
1092
+ })),
988
1093
  connectors,
989
1094
  mcp_config_snippets: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.mcp_config_snippet])),
990
1095
  connect_plans: Object.fromEntries(connectors.map((connector) => [connector.client_id, connector.connect_plan])),
991
- next_commands: setupNextCommands(displays.bundle, displays.export, clients, writeConnectors),
1096
+ next_commands: setupNextCommands(displays.bundle, displays.export, clients, connectorWritesRequested && (!connectInstalled || anyConnectorWritePerformed)),
992
1097
  checks: doctor.checks,
993
1098
  claim_boundaries: { ...SETUP_CLAIM_BOUNDARIES },
994
1099
  }, io);
@@ -1902,7 +2007,8 @@ function usage() {
1902
2007
  setup_options: {
1903
2008
  '--bundle <path>': 'Bundle JSON to create. Defaults to .enigma/bundle.json.',
1904
2009
  '--out-dir <path>': 'Directory for context-pack.json, export.json, and verify-report.json. Defaults to the bundle directory.',
1905
- '--client <id>': `Client to plan; repeat or comma-separate. Defaults to ${DEFAULT_SETUP_CLIENTS.join(', ')}.`,
2010
+ '--client <id|auto>': `Client to plan; repeat or comma-separate. Use auto to plan installed/config-present clients, falling back to ${DEFAULT_SETUP_CLIENTS.join(', ')}.`,
2011
+ '--connect-installed': 'Auto-select installed/config-present clients and write only those existing client configs; missing client configs are reported and skipped.',
1906
2012
  '--memory-file <path>': 'Read local memory text from a file without echoing plaintext. Alias: --text-file.',
1907
2013
  '--memory-text <text>': 'Inline demo-only memory text. Avoid for private content because argv can be logged.',
1908
2014
  '--overwrite': 'Replace existing local setup artifacts.',
@@ -1296,13 +1296,34 @@ export async function loadRelayStateFromFile(path, options = {}) {
1296
1296
  }
1297
1297
  }
1298
1298
 
1299
+ function retryableRelayRenameError(error) {
1300
+ return error?.code === 'EBUSY' || error?.code === 'EPERM' || error?.code === 'EACCES';
1301
+ }
1302
+
1303
+ async function delayRelayRenameRetry(ms) {
1304
+ await new Promise((resolve) => setTimeout(resolve, ms));
1305
+ }
1306
+
1307
+ async function renameRelayStateAtomically(tempPath, filePath) {
1308
+ const delays = [10, 25, 50, 100, 200];
1309
+ for (let attempt = 0; attempt <= delays.length; attempt += 1) {
1310
+ try {
1311
+ await rename(tempPath, filePath);
1312
+ return;
1313
+ } catch (error) {
1314
+ if (attempt === delays.length || !retryableRelayRenameError(error)) throw error;
1315
+ await delayRelayRenameRetry(delays[attempt]);
1316
+ }
1317
+ }
1318
+ }
1319
+
1299
1320
  export async function saveRelayStateToFile(state, path) {
1300
1321
  const filePath = assertString(path, 'relay state file path');
1301
1322
  const snapshot = serializeRelayState(state);
1302
1323
  const tempPath = join(dirname(filePath), `.${basename(filePath)}.${randomBytes(6).toString('hex')}.tmp`);
1303
1324
  try {
1304
1325
  await writeFile(tempPath, `${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
1305
- await rename(tempPath, filePath);
1326
+ await renameRelayStateAtomically(tempPath, filePath);
1306
1327
  } catch (error) {
1307
1328
  await unlink(tempPath).catch(() => undefined);
1308
1329
  throw error;
@@ -9,6 +9,27 @@ For most developers, start with the installed CLI before reading the SDK interna
9
9
  ```sh
10
10
  npm install -g enigma-memory
11
11
  enigma setup --overwrite
12
+ ```
13
+
14
+ `enigma setup --overwrite` is the safe default. It writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON without printing raw memory plaintext. It does not write third-party app configs.
15
+
16
+ To let setup auto-detect installed or already-configured clients and report the connector plan without mutating client configs:
17
+
18
+ ```sh
19
+ enigma setup --client auto --overwrite
20
+ ```
21
+
22
+ To explicitly write connector entries for installed/config-present clients only:
23
+
24
+ ```sh
25
+ enigma setup --connect-installed --overwrite
26
+ ```
27
+
28
+ `--client auto` selects clients found by connector detection and falls back to the default setup client list when none are present. The setup output lists selected clients, skipped clients, and skip reasons. `--connect-installed` implies auto selection, writes only for installed/config-present clients, and skips missing configs instead of creating every default client config. Only explicit write flags mutate client configs; `enigma connect <client>` without `--dry-run` remains the single-client write path, and existing `enigma setup --write-connectors` behavior for explicit/default clients is unchanged. Treat provider-native memory as non-canonical cache only; the local Enigma vault is canonical.
29
+
30
+ After setup, use the same local vault from the CLI or connected clients:
31
+
32
+ ```sh
12
33
  enigma remember --text-file ./memory.txt
13
34
  enigma search --query "..."
14
35
  enigma context --query "..." --optimize
@@ -16,8 +37,6 @@ enigma verify --export ./.enigma/export.json
16
37
  enigma connect claude-desktop --dry-run
17
38
  ```
18
39
 
19
- `enigma setup --overwrite` writes local Enigma artifacts under the workspace `.enigma` path and emits deterministic, public-safe JSON. It does not write third-party app configs unless you explicitly run `enigma connect <client>` without `--dry-run`. Treat provider-native memory as cache only; the local Enigma vault is canonical.
20
-
21
40
  ## Copyable starting points
22
41
 
23
42
  - SDK/API guide: [`docs/sdk-api.md`](./sdk-api.md)
@@ -41,7 +60,7 @@ The example app prints ids, counts, roots, and verification status only. It does
41
60
 
42
61
  ## CLI and CI loop
43
62
 
44
- The CI example installs Node 24, installs the published `enigma-memory@0.1.6` package, runs:
63
+ The CI example installs Node 24, installs the published `enigma-memory@0.1.8` package, runs:
45
64
 
46
65
  ```sh
47
66
  npx --yes --package enigma-memory enigma setup --overwrite
@@ -65,7 +84,7 @@ Use the workflow as a template in a consumer repository. It is intentionally lim
65
84
 
66
85
  ## MCP client loop
67
86
 
68
- The same installed package can be used by Claude Desktop, Cursor, Kimi Code, or any generic MCP client. Copy one snippet, replace the bundle path with the local path from your setup output, and restart the client.
87
+ The same installed package can be used by Claude Desktop, Cursor, Kimi Code, or any generic MCP client. The smooth setup path is `enigma setup --client auto --overwrite` to plan detected clients, then `enigma setup --connect-installed --overwrite` only when you explicitly want setup to write installed/config-present client configs. Manual snippets remain useful when a client needs a copied entry; replace the bundle path with the local path from your setup output, and restart the client.
69
88
 
70
89
  Claude Desktop:
71
90
 
package/docs/sdk-api.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SDK and API guide
2
2
 
3
- This guide covers the public package imports for `enigma-memory@0.1.6`. The SDK runs locally by default: vaults, passports, context packs, receipts, relay/gateway demo state, storage contracts, metering artifacts, and settlement artifacts are package-level developer surfaces. They are not evidence of hosted Enigma cloud, provider-side deletion, provider model forgetting, token ROI, invoice savings, compliance certification, or benchmark leadership.
3
+ This guide covers the public package imports for `enigma-memory@0.1.8`. The SDK runs locally by default: vaults, passports, context packs, receipts, relay/gateway demo state, storage contracts, metering artifacts, and settlement artifacts are package-level developer surfaces. They are not evidence of hosted Enigma cloud, provider-side deletion, provider model forgetting, token ROI, invoice savings, compliance certification, or benchmark leadership.
4
4
 
5
5
  ## Install and import style
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "enigma-memory",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "Provider-agnostic AI memory passport and offline-verifiable proof layer.",
6
6
  "license": "Apache-2.0",
@@ -17,7 +17,7 @@ import {
17
17
  const DEFAULT_BUNDLE = '.enigma/bundle.json';
18
18
  const JSONRPC_VERSION = '2.0';
19
19
  const MCP_PROTOCOL_VERSION = '2024-11-05';
20
- const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.6' });
20
+ const SERVER_INFO = Object.freeze({ name: 'enigma-mcp-server', version: '0.1.8' });
21
21
  const JSON_RPC_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/;
22
22
  const JSON_RPC_ERROR = Object.freeze({
23
23
  INVALID_REQUEST: -32600,
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url';
6
6
 
7
7
  export const INSTALLER_ASSET_SCHEMA = 'enigma.installer_assets.v1';
8
8
  export const INSTALLER_ASSET_PACKAGE = 'enigma-memory';
9
- export const INSTALLER_ASSET_VERSION = '0.1.6';
9
+ export const INSTALLER_ASSET_VERSION = '0.1.8';
10
10
  export const INSTALLER_ASSET_GENERATED_AT = '1970-01-01T00:00:00.000Z';
11
11
 
12
12
  const SCRIPT_PATH = fileURLToPath(import.meta.url);
@@ -995,7 +995,7 @@ function buildSuiteReport(datasetRows, topK, options) {
995
995
  generated_at: options.generated_at ?? new Date().toISOString(),
996
996
  package: {
997
997
  name: 'enigma-memory',
998
- version: '0.1.6',
998
+ version: '0.1.8',
999
999
  },
1000
1000
  public_safe: true,
1001
1001
  top_k: topK,