@everworker/oneringai 0.3.1 → 0.3.2

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.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var crypto2 = require('crypto');
4
4
  var jose = require('jose');
5
- var fs17 = require('fs');
5
+ var fs18 = require('fs');
6
6
  var eventemitter3 = require('eventemitter3');
7
7
  var path2 = require('path');
8
8
  var TurndownService = require('turndown');
@@ -17,7 +17,7 @@ var z = require('zod/v4');
17
17
  var spawn = require('cross-spawn');
18
18
  var process2 = require('process');
19
19
  var stream = require('stream');
20
- var fs16 = require('fs/promises');
20
+ var fs17 = require('fs/promises');
21
21
  var simpleIcons = require('simple-icons');
22
22
  var child_process = require('child_process');
23
23
  var util = require('util');
@@ -45,7 +45,7 @@ function _interopNamespace(e) {
45
45
  }
46
46
 
47
47
  var crypto2__namespace = /*#__PURE__*/_interopNamespace(crypto2);
48
- var fs17__namespace = /*#__PURE__*/_interopNamespace(fs17);
48
+ var fs18__namespace = /*#__PURE__*/_interopNamespace(fs18);
49
49
  var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
50
50
  var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
51
51
  var os2__namespace = /*#__PURE__*/_interopNamespace(os2);
@@ -55,7 +55,7 @@ var z4mini__namespace = /*#__PURE__*/_interopNamespace(z4mini);
55
55
  var z__namespace = /*#__PURE__*/_interopNamespace(z);
56
56
  var spawn__default = /*#__PURE__*/_interopDefault(spawn);
57
57
  var process2__default = /*#__PURE__*/_interopDefault(process2);
58
- var fs16__namespace = /*#__PURE__*/_interopNamespace(fs16);
58
+ var fs17__namespace = /*#__PURE__*/_interopNamespace(fs17);
59
59
  var simpleIcons__namespace = /*#__PURE__*/_interopNamespace(simpleIcons);
60
60
  var vm__namespace = /*#__PURE__*/_interopNamespace(vm);
61
61
 
@@ -673,7 +673,7 @@ var init_JWTBearer = __esm({
673
673
  this.privateKey = config.privateKey;
674
674
  } else if (config.privateKeyPath) {
675
675
  try {
676
- this.privateKey = fs17__namespace.readFileSync(config.privateKeyPath, "utf8");
676
+ this.privateKey = fs18__namespace.readFileSync(config.privateKeyPath, "utf8");
677
677
  } catch (error) {
678
678
  throw new Error(`Failed to read private key from ${config.privateKeyPath}: ${error.message}`);
679
679
  }
@@ -1432,10 +1432,10 @@ var init_Logger = __esm({
1432
1432
  initFileStream(filePath) {
1433
1433
  try {
1434
1434
  const dir = path2__namespace.dirname(filePath);
1435
- if (!fs17__namespace.existsSync(dir)) {
1436
- fs17__namespace.mkdirSync(dir, { recursive: true });
1435
+ if (!fs18__namespace.existsSync(dir)) {
1436
+ fs18__namespace.mkdirSync(dir, { recursive: true });
1437
1437
  }
1438
- this.fileStream = fs17__namespace.createWriteStream(filePath, {
1438
+ this.fileStream = fs18__namespace.createWriteStream(filePath, {
1439
1439
  flags: "a",
1440
1440
  // append mode
1441
1441
  encoding: "utf8"
@@ -9165,12 +9165,12 @@ var require_dist = __commonJS({
9165
9165
  throw new Error(`Unknown format "${name}"`);
9166
9166
  return f;
9167
9167
  };
9168
- function addFormats(ajv, list, fs18, exportName) {
9168
+ function addFormats(ajv, list, fs19, exportName) {
9169
9169
  var _a;
9170
9170
  var _b;
9171
9171
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
9172
9172
  for (const f of list)
9173
- ajv.addFormat(f, fs18[f]);
9173
+ ajv.addFormat(f, fs19[f]);
9174
9174
  }
9175
9175
  module.exports = exports$1 = formatsPlugin;
9176
9176
  Object.defineProperty(exports$1, "__esModule", { value: true });
@@ -10173,6 +10173,11 @@ var DEFAULT_ALLOWLIST = [
10173
10173
  "instructions_remove",
10174
10174
  "instructions_list",
10175
10175
  "instructions_clear",
10176
+ // User info tools (user-specific data - safe)
10177
+ "user_info_set",
10178
+ "user_info_get",
10179
+ "user_info_remove",
10180
+ "user_info_clear",
10176
10181
  // Meta-tools (internal coordination)
10177
10182
  "_start_planning",
10178
10183
  "_modify_plan",
@@ -14897,7 +14902,7 @@ var FilePersistentInstructionsStorage = class {
14897
14902
  */
14898
14903
  async load() {
14899
14904
  try {
14900
- const raw = await fs17.promises.readFile(this.filePath, "utf-8");
14905
+ const raw = await fs18.promises.readFile(this.filePath, "utf-8");
14901
14906
  const data = JSON.parse(raw);
14902
14907
  if (data.version === 2 && Array.isArray(data.entries)) {
14903
14908
  return data.entries.length > 0 ? data.entries : null;
@@ -14909,7 +14914,7 @@ var FilePersistentInstructionsStorage = class {
14909
14914
  }
14910
14915
  }
14911
14916
  try {
14912
- const content = await fs17.promises.readFile(this.legacyFilePath, "utf-8");
14917
+ const content = await fs18.promises.readFile(this.legacyFilePath, "utf-8");
14913
14918
  const trimmed = content.trim();
14914
14919
  if (!trimmed) return null;
14915
14920
  const now = Date.now();
@@ -14939,11 +14944,11 @@ var FilePersistentInstructionsStorage = class {
14939
14944
  };
14940
14945
  const tempPath = `${this.filePath}.tmp`;
14941
14946
  try {
14942
- await fs17.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
14943
- await fs17.promises.rename(tempPath, this.filePath);
14947
+ await fs18.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
14948
+ await fs18.promises.rename(tempPath, this.filePath);
14944
14949
  } catch (error) {
14945
14950
  try {
14946
- await fs17.promises.unlink(tempPath);
14951
+ await fs18.promises.unlink(tempPath);
14947
14952
  } catch {
14948
14953
  }
14949
14954
  throw error;
@@ -14955,7 +14960,7 @@ var FilePersistentInstructionsStorage = class {
14955
14960
  */
14956
14961
  async delete() {
14957
14962
  try {
14958
- await fs17.promises.unlink(this.filePath);
14963
+ await fs18.promises.unlink(this.filePath);
14959
14964
  } catch (error) {
14960
14965
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
14961
14966
  throw error;
@@ -14968,11 +14973,11 @@ var FilePersistentInstructionsStorage = class {
14968
14973
  */
14969
14974
  async exists() {
14970
14975
  try {
14971
- await fs17.promises.access(this.filePath);
14976
+ await fs18.promises.access(this.filePath);
14972
14977
  return true;
14973
14978
  } catch {
14974
14979
  try {
14975
- await fs17.promises.access(this.legacyFilePath);
14980
+ await fs18.promises.access(this.legacyFilePath);
14976
14981
  return true;
14977
14982
  } catch {
14978
14983
  return false;
@@ -14996,7 +15001,7 @@ var FilePersistentInstructionsStorage = class {
14996
15001
  */
14997
15002
  async ensureDirectory() {
14998
15003
  try {
14999
- await fs17.promises.mkdir(this.directory, { recursive: true });
15004
+ await fs18.promises.mkdir(this.directory, { recursive: true });
15000
15005
  } catch (error) {
15001
15006
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
15002
15007
  throw error;
@@ -15008,7 +15013,7 @@ var FilePersistentInstructionsStorage = class {
15008
15013
  */
15009
15014
  async removeLegacyFile() {
15010
15015
  try {
15011
- await fs17.promises.unlink(this.legacyFilePath);
15016
+ await fs18.promises.unlink(this.legacyFilePath);
15012
15017
  } catch (error) {
15013
15018
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
15014
15019
  console.warn(`Failed to remove legacy instructions file: ${this.legacyFilePath}`);
@@ -15472,6 +15477,572 @@ ${entry.content}`).join("\n\n");
15472
15477
  };
15473
15478
  }
15474
15479
  };
15480
+ function getDefaultBaseDirectory2() {
15481
+ const platform2 = process.platform;
15482
+ if (platform2 === "win32") {
15483
+ const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
15484
+ if (appData) {
15485
+ return path2.join(appData, "oneringai", "users");
15486
+ }
15487
+ }
15488
+ return path2.join(os2.homedir(), ".oneringai", "users");
15489
+ }
15490
+ var DEFAULT_USER_ID = "default";
15491
+ function sanitizeUserId(userId) {
15492
+ if (!userId) return DEFAULT_USER_ID;
15493
+ return userId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || DEFAULT_USER_ID;
15494
+ }
15495
+ var FileUserInfoStorage = class {
15496
+ baseDirectory;
15497
+ filename;
15498
+ constructor(config) {
15499
+ this.baseDirectory = config?.baseDirectory ?? getDefaultBaseDirectory2();
15500
+ this.filename = config?.filename ?? "user_info.json";
15501
+ }
15502
+ /**
15503
+ * Get the directory path for a specific user
15504
+ */
15505
+ getUserDirectory(userId) {
15506
+ const sanitizedId = sanitizeUserId(userId);
15507
+ return path2.join(this.baseDirectory, sanitizedId);
15508
+ }
15509
+ /**
15510
+ * Get the file path for a specific user
15511
+ */
15512
+ getUserFilePath(userId) {
15513
+ return path2.join(this.getUserDirectory(userId), this.filename);
15514
+ }
15515
+ /**
15516
+ * Load user info entries from file for a specific user
15517
+ */
15518
+ async load(userId) {
15519
+ const filePath = this.getUserFilePath(userId);
15520
+ try {
15521
+ const raw = await fs18.promises.readFile(filePath, "utf-8");
15522
+ const data = JSON.parse(raw);
15523
+ if (data.version === 1 && Array.isArray(data.entries)) {
15524
+ return data.entries.length > 0 ? data.entries : null;
15525
+ }
15526
+ return null;
15527
+ } catch (error) {
15528
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
15529
+ throw error;
15530
+ }
15531
+ return null;
15532
+ }
15533
+ }
15534
+ /**
15535
+ * Save user info entries to file for a specific user
15536
+ * Creates directory if it doesn't exist.
15537
+ */
15538
+ async save(userId, entries) {
15539
+ const directory = this.getUserDirectory(userId);
15540
+ const filePath = this.getUserFilePath(userId);
15541
+ await this.ensureDirectory(directory);
15542
+ const data = {
15543
+ version: 1,
15544
+ userId: userId || DEFAULT_USER_ID,
15545
+ entries
15546
+ };
15547
+ const tempPath = `${filePath}.tmp`;
15548
+ try {
15549
+ await fs18.promises.writeFile(tempPath, JSON.stringify(data, null, 2), "utf-8");
15550
+ await fs18.promises.rename(tempPath, filePath);
15551
+ } catch (error) {
15552
+ try {
15553
+ await fs18.promises.unlink(tempPath);
15554
+ } catch {
15555
+ }
15556
+ throw error;
15557
+ }
15558
+ }
15559
+ /**
15560
+ * Delete user info file for a specific user
15561
+ */
15562
+ async delete(userId) {
15563
+ const filePath = this.getUserFilePath(userId);
15564
+ try {
15565
+ await fs18.promises.unlink(filePath);
15566
+ } catch (error) {
15567
+ if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
15568
+ throw error;
15569
+ }
15570
+ }
15571
+ }
15572
+ /**
15573
+ * Check if user info file exists for a specific user
15574
+ */
15575
+ async exists(userId) {
15576
+ const filePath = this.getUserFilePath(userId);
15577
+ try {
15578
+ await fs18.promises.access(filePath);
15579
+ return true;
15580
+ } catch {
15581
+ return false;
15582
+ }
15583
+ }
15584
+ /**
15585
+ * Get the file path for a specific user (for display/debugging)
15586
+ */
15587
+ getPath(userId) {
15588
+ return this.getUserFilePath(userId);
15589
+ }
15590
+ /**
15591
+ * Ensure the directory exists
15592
+ */
15593
+ async ensureDirectory(directory) {
15594
+ try {
15595
+ await fs18.promises.mkdir(directory, { recursive: true });
15596
+ } catch (error) {
15597
+ if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
15598
+ throw error;
15599
+ }
15600
+ }
15601
+ }
15602
+ };
15603
+
15604
+ // src/core/context-nextgen/plugins/UserInfoPluginNextGen.ts
15605
+ init_StorageRegistry();
15606
+ var DEFAULT_MAX_TOTAL_SIZE = 1e5;
15607
+ var DEFAULT_MAX_ENTRIES2 = 100;
15608
+ var KEY_MAX_LENGTH2 = 100;
15609
+ var KEY_PATTERN2 = /^[a-zA-Z0-9_-]+$/;
15610
+ var USER_INFO_INSTRUCTIONS = `User Info stores key-value information about the current user.
15611
+ Data is user-specific and persists across sessions and agents.
15612
+ User info is automatically shown in context \u2014 no need to call user_info_get every turn.
15613
+
15614
+ **To manage:**
15615
+ - \`user_info_set(key, value, description?)\`: Store/update user information
15616
+ - \`user_info_get(key?)\`: Retrieve one entry by key, or all entries if no key
15617
+ - \`user_info_remove(key)\`: Remove a specific entry
15618
+ - \`user_info_clear(confirm: true)\`: Remove all entries (destructive!)
15619
+
15620
+ **Use for:** User preferences, context, metadata (theme, language, timezone, role, etc.) It is also perfectly fine to search the web and other external sources for information about the user and then store it in user info for future use.
15621
+
15622
+ **Important:** Do not store sensitive information (passwords, tokens, PII) in user info. It is not encrypted and may be accessible to other parts of the system. Always follow best practices for security.
15623
+
15624
+ **Rules after each user message:** If the user provides new information about themselves, update user info accordingly. If they ask to change or remove existing information, do that as well. Always keep user info up to date with the latest information provided by the user. Learn about the user proactively!`;
15625
+ var userInfoSetDefinition = {
15626
+ type: "function",
15627
+ function: {
15628
+ name: "user_info_set",
15629
+ description: `Store or update user information by key. Data persists across sessions.
15630
+ If the key exists, it will be updated. If not, a new entry is created.`,
15631
+ parameters: {
15632
+ type: "object",
15633
+ properties: {
15634
+ key: {
15635
+ type: "string",
15636
+ description: "Unique key for the information (alphanumeric, dash, underscore; max 100 chars)"
15637
+ },
15638
+ value: {
15639
+ description: "Value to store (any JSON-serializable data: string, number, boolean, object, array)"
15640
+ },
15641
+ description: {
15642
+ type: "string",
15643
+ description: "Optional description for self-documentation"
15644
+ }
15645
+ },
15646
+ required: ["key", "value"]
15647
+ }
15648
+ }
15649
+ };
15650
+ var userInfoGetDefinition = {
15651
+ type: "function",
15652
+ function: {
15653
+ name: "user_info_get",
15654
+ description: "Retrieve user information. If key is provided, returns that entry. Otherwise returns all entries.",
15655
+ parameters: {
15656
+ type: "object",
15657
+ properties: {
15658
+ key: {
15659
+ type: "string",
15660
+ description: "Key of the entry to retrieve (optional - omit to get all entries)"
15661
+ }
15662
+ },
15663
+ required: []
15664
+ }
15665
+ }
15666
+ };
15667
+ var userInfoRemoveDefinition = {
15668
+ type: "function",
15669
+ function: {
15670
+ name: "user_info_remove",
15671
+ description: "Remove a specific user information entry by key.",
15672
+ parameters: {
15673
+ type: "object",
15674
+ properties: {
15675
+ key: {
15676
+ type: "string",
15677
+ description: "Key of the entry to remove"
15678
+ }
15679
+ },
15680
+ required: ["key"]
15681
+ }
15682
+ }
15683
+ };
15684
+ var userInfoClearDefinition = {
15685
+ type: "function",
15686
+ function: {
15687
+ name: "user_info_clear",
15688
+ description: "Clear all user information entries (DESTRUCTIVE). Requires confirmation.",
15689
+ parameters: {
15690
+ type: "object",
15691
+ properties: {
15692
+ confirm: {
15693
+ type: "boolean",
15694
+ description: "Must be true to confirm deletion"
15695
+ }
15696
+ },
15697
+ required: ["confirm"]
15698
+ }
15699
+ }
15700
+ };
15701
+ function validateKey2(key) {
15702
+ if (typeof key !== "string") return "Key must be a string";
15703
+ const trimmed = key.trim();
15704
+ if (trimmed.length === 0) return "Key cannot be empty";
15705
+ if (trimmed.length > KEY_MAX_LENGTH2) return `Key exceeds maximum length (${KEY_MAX_LENGTH2} chars)`;
15706
+ if (!KEY_PATTERN2.test(trimmed)) return "Key must contain only alphanumeric characters, dashes, and underscores";
15707
+ return null;
15708
+ }
15709
+ function getValueType(value) {
15710
+ if (value === null) return "null";
15711
+ if (Array.isArray(value)) return "array";
15712
+ return typeof value;
15713
+ }
15714
+ function calculateValueSize(value) {
15715
+ const json = JSON.stringify(value);
15716
+ return Buffer.byteLength(json, "utf-8");
15717
+ }
15718
+ function buildStorageContext(toolContext) {
15719
+ const global2 = exports.StorageRegistry.getContext();
15720
+ if (global2) return global2;
15721
+ if (toolContext?.userId) return { userId: toolContext.userId };
15722
+ return void 0;
15723
+ }
15724
+ function formatValue(value) {
15725
+ if (value === null) return "null";
15726
+ if (typeof value === "string") return value;
15727
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
15728
+ return JSON.stringify(value);
15729
+ }
15730
+ var UserInfoPluginNextGen = class {
15731
+ name = "user_info";
15732
+ _destroyed = false;
15733
+ _storage = null;
15734
+ /** In-memory cache of entries */
15735
+ _entries = /* @__PURE__ */ new Map();
15736
+ /** Whether entries have been loaded from storage */
15737
+ _initialized = false;
15738
+ maxTotalSize;
15739
+ maxEntries;
15740
+ estimator = simpleTokenEstimator;
15741
+ explicitStorage;
15742
+ /** UserId for getContent() and lazy initialization */
15743
+ userId;
15744
+ _tokenCache = null;
15745
+ _instructionsTokenCache = null;
15746
+ constructor(config) {
15747
+ this.maxTotalSize = config?.maxTotalSize ?? DEFAULT_MAX_TOTAL_SIZE;
15748
+ this.maxEntries = config?.maxEntries ?? DEFAULT_MAX_ENTRIES2;
15749
+ this.explicitStorage = config?.storage;
15750
+ this.userId = config?.userId;
15751
+ }
15752
+ // ============================================================================
15753
+ // IContextPluginNextGen Implementation
15754
+ // ============================================================================
15755
+ getInstructions() {
15756
+ return USER_INFO_INSTRUCTIONS;
15757
+ }
15758
+ async getContent() {
15759
+ await this.ensureInitialized();
15760
+ if (this._entries.size === 0) {
15761
+ this._tokenCache = 0;
15762
+ return null;
15763
+ }
15764
+ const rendered = this.renderContent();
15765
+ this._tokenCache = this.estimator.estimateTokens(rendered);
15766
+ return rendered;
15767
+ }
15768
+ getContents() {
15769
+ return new Map(this._entries);
15770
+ }
15771
+ getTokenSize() {
15772
+ return this._tokenCache ?? 0;
15773
+ }
15774
+ getInstructionsTokenSize() {
15775
+ if (this._instructionsTokenCache === null) {
15776
+ this._instructionsTokenCache = this.estimator.estimateTokens(USER_INFO_INSTRUCTIONS);
15777
+ }
15778
+ return this._instructionsTokenCache;
15779
+ }
15780
+ isCompactable() {
15781
+ return false;
15782
+ }
15783
+ async compact(_targetTokensToFree) {
15784
+ return 0;
15785
+ }
15786
+ getTools() {
15787
+ return [
15788
+ this.createUserInfoSetTool(),
15789
+ this.createUserInfoGetTool(),
15790
+ this.createUserInfoRemoveTool(),
15791
+ this.createUserInfoClearTool()
15792
+ ];
15793
+ }
15794
+ destroy() {
15795
+ if (this._destroyed) return;
15796
+ this._entries.clear();
15797
+ this._destroyed = true;
15798
+ this._tokenCache = null;
15799
+ }
15800
+ getState() {
15801
+ return {
15802
+ version: 1,
15803
+ entries: Array.from(this._entries.values()),
15804
+ userId: this.userId
15805
+ };
15806
+ }
15807
+ restoreState(state) {
15808
+ if (!state || typeof state !== "object") return;
15809
+ const s = state;
15810
+ if ("version" in s && s.version === 1 && Array.isArray(s.entries)) {
15811
+ this._entries.clear();
15812
+ for (const entry of s.entries) {
15813
+ this._entries.set(entry.id, entry);
15814
+ }
15815
+ this._initialized = true;
15816
+ this._tokenCache = null;
15817
+ }
15818
+ }
15819
+ // ============================================================================
15820
+ // Public API
15821
+ // ============================================================================
15822
+ /**
15823
+ * Check if initialized
15824
+ */
15825
+ get isInitialized() {
15826
+ return this._initialized;
15827
+ }
15828
+ // ============================================================================
15829
+ // Private Helpers
15830
+ // ============================================================================
15831
+ assertNotDestroyed() {
15832
+ if (this._destroyed) {
15833
+ throw new Error("UserInfoPluginNextGen is destroyed");
15834
+ }
15835
+ }
15836
+ /**
15837
+ * Lazy load entries from storage
15838
+ */
15839
+ async ensureInitialized() {
15840
+ if (this._initialized || this._destroyed) return;
15841
+ try {
15842
+ const storage = this.resolveStorage();
15843
+ const entries = await storage.load(this.userId);
15844
+ this._entries.clear();
15845
+ if (entries) {
15846
+ for (const entry of entries) {
15847
+ this._entries.set(entry.id, entry);
15848
+ }
15849
+ }
15850
+ this._initialized = true;
15851
+ } catch (error) {
15852
+ console.warn(`Failed to load user info for userId '${this.userId ?? "default"}':`, error);
15853
+ this._entries.clear();
15854
+ this._initialized = true;
15855
+ }
15856
+ this._tokenCache = null;
15857
+ }
15858
+ /**
15859
+ * Render entries as markdown for context injection
15860
+ */
15861
+ renderContent() {
15862
+ const sorted = Array.from(this._entries.values()).sort((a, b) => a.createdAt - b.createdAt);
15863
+ return sorted.map((entry) => `### ${entry.id}
15864
+ ${formatValue(entry.value)}`).join("\n\n");
15865
+ }
15866
+ /**
15867
+ * Resolve storage instance (lazy singleton)
15868
+ */
15869
+ resolveStorage(context) {
15870
+ if (this._storage) return this._storage;
15871
+ if (this.explicitStorage) {
15872
+ this._storage = this.explicitStorage;
15873
+ return this._storage;
15874
+ }
15875
+ const factory = exports.StorageRegistry.get("userInfo");
15876
+ if (factory) {
15877
+ this._storage = factory(buildStorageContext(context));
15878
+ return this._storage;
15879
+ }
15880
+ this._storage = new FileUserInfoStorage();
15881
+ return this._storage;
15882
+ }
15883
+ /**
15884
+ * Persist current entries to storage
15885
+ */
15886
+ async persistToStorage(userId) {
15887
+ const storage = this.resolveStorage();
15888
+ if (this._entries.size === 0) {
15889
+ await storage.delete(userId);
15890
+ } else {
15891
+ await storage.save(userId, Array.from(this._entries.values()));
15892
+ }
15893
+ }
15894
+ // ============================================================================
15895
+ // Tool Factories
15896
+ // ============================================================================
15897
+ createUserInfoSetTool() {
15898
+ return {
15899
+ definition: userInfoSetDefinition,
15900
+ execute: async (args, context) => {
15901
+ this.assertNotDestroyed();
15902
+ await this.ensureInitialized();
15903
+ const userId = context?.userId ?? this.userId;
15904
+ const key = args.key;
15905
+ const value = args.value;
15906
+ const description = args.description;
15907
+ const keyError = validateKey2(key);
15908
+ if (keyError) {
15909
+ return { error: keyError };
15910
+ }
15911
+ const trimmedKey = key.trim();
15912
+ if (value === void 0) {
15913
+ return { error: "Value cannot be undefined. Use null for explicit null value." };
15914
+ }
15915
+ if (!this._entries.has(trimmedKey) && this._entries.size >= this.maxEntries) {
15916
+ return { error: `Maximum number of entries reached (${this.maxEntries})` };
15917
+ }
15918
+ const valueSize = calculateValueSize(value);
15919
+ let currentTotal = 0;
15920
+ for (const e of this._entries.values()) {
15921
+ currentTotal += calculateValueSize(e.value);
15922
+ }
15923
+ const existingSize = this._entries.has(trimmedKey) ? calculateValueSize(this._entries.get(trimmedKey).value) : 0;
15924
+ const newTotal = currentTotal - existingSize + valueSize;
15925
+ if (newTotal > this.maxTotalSize) {
15926
+ return { error: `Total size would exceed maximum (${this.maxTotalSize} bytes)` };
15927
+ }
15928
+ const now = Date.now();
15929
+ const existing = this._entries.get(trimmedKey);
15930
+ const entry = {
15931
+ id: trimmedKey,
15932
+ value,
15933
+ valueType: getValueType(value),
15934
+ description,
15935
+ createdAt: existing?.createdAt ?? now,
15936
+ updatedAt: now
15937
+ };
15938
+ this._entries.set(trimmedKey, entry);
15939
+ this._tokenCache = null;
15940
+ await this.persistToStorage(userId);
15941
+ return {
15942
+ success: true,
15943
+ message: existing ? `User info '${trimmedKey}' updated` : `User info '${trimmedKey}' added`,
15944
+ key: trimmedKey,
15945
+ valueType: entry.valueType,
15946
+ valueSize
15947
+ };
15948
+ },
15949
+ permission: { scope: "always", riskLevel: "low" },
15950
+ describeCall: (args) => `set user info '${args.key}'`
15951
+ };
15952
+ }
15953
+ createUserInfoGetTool() {
15954
+ return {
15955
+ definition: userInfoGetDefinition,
15956
+ execute: async (args, _context) => {
15957
+ this.assertNotDestroyed();
15958
+ await this.ensureInitialized();
15959
+ const key = args.key;
15960
+ if (this._entries.size === 0) {
15961
+ return { error: "User info not found" };
15962
+ }
15963
+ if (key !== void 0) {
15964
+ const trimmedKey = key.trim();
15965
+ const entry = this._entries.get(trimmedKey);
15966
+ if (!entry) {
15967
+ return { error: `User info '${trimmedKey}' not found` };
15968
+ }
15969
+ return {
15970
+ key: entry.id,
15971
+ value: entry.value,
15972
+ valueType: entry.valueType,
15973
+ description: entry.description,
15974
+ createdAt: entry.createdAt,
15975
+ updatedAt: entry.updatedAt
15976
+ };
15977
+ }
15978
+ const entries = Array.from(this._entries.values());
15979
+ return {
15980
+ count: entries.length,
15981
+ entries: entries.map((e) => ({
15982
+ key: e.id,
15983
+ value: e.value,
15984
+ valueType: e.valueType,
15985
+ description: e.description,
15986
+ createdAt: e.createdAt,
15987
+ updatedAt: e.updatedAt
15988
+ }))
15989
+ };
15990
+ },
15991
+ permission: { scope: "always", riskLevel: "low" },
15992
+ describeCall: (args) => args.key ? `get user info '${args.key}'` : "get all user info"
15993
+ };
15994
+ }
15995
+ createUserInfoRemoveTool() {
15996
+ return {
15997
+ definition: userInfoRemoveDefinition,
15998
+ execute: async (args, context) => {
15999
+ this.assertNotDestroyed();
16000
+ await this.ensureInitialized();
16001
+ const userId = context?.userId ?? this.userId;
16002
+ const key = args.key;
16003
+ if (!key || typeof key !== "string" || key.trim().length === 0) {
16004
+ return { error: "Key is required" };
16005
+ }
16006
+ const trimmedKey = key.trim();
16007
+ if (!this._entries.has(trimmedKey)) {
16008
+ return { error: `User info '${trimmedKey}' not found` };
16009
+ }
16010
+ this._entries.delete(trimmedKey);
16011
+ this._tokenCache = null;
16012
+ await this.persistToStorage(userId);
16013
+ return {
16014
+ success: true,
16015
+ message: `User info '${trimmedKey}' removed`,
16016
+ key: trimmedKey
16017
+ };
16018
+ },
16019
+ permission: { scope: "always", riskLevel: "low" },
16020
+ describeCall: (args) => `remove user info '${args.key}'`
16021
+ };
16022
+ }
16023
+ createUserInfoClearTool() {
16024
+ return {
16025
+ definition: userInfoClearDefinition,
16026
+ execute: async (args, context) => {
16027
+ this.assertNotDestroyed();
16028
+ const userId = context?.userId ?? this.userId;
16029
+ if (args.confirm !== true) {
16030
+ return { error: "Must pass confirm: true to clear user info" };
16031
+ }
16032
+ this._entries.clear();
16033
+ this._tokenCache = null;
16034
+ const storage = this.resolveStorage(context);
16035
+ await storage.delete(userId);
16036
+ return {
16037
+ success: true,
16038
+ message: "All user information cleared"
16039
+ };
16040
+ },
16041
+ permission: { scope: "once", riskLevel: "medium" },
16042
+ describeCall: () => "clear user info"
16043
+ };
16044
+ }
16045
+ };
15475
16046
 
15476
16047
  // src/core/context-nextgen/AgentContextNextGen.ts
15477
16048
  init_StorageRegistry();
@@ -16120,7 +16691,8 @@ var StrategyRegistry = class {
16120
16691
  var DEFAULT_FEATURES = {
16121
16692
  workingMemory: true,
16122
16693
  inContextMemory: false,
16123
- persistentInstructions: false
16694
+ persistentInstructions: false,
16695
+ userInfo: false
16124
16696
  };
16125
16697
  var DEFAULT_CONFIG2 = {
16126
16698
  responseReserve: 4096,
@@ -16238,6 +16810,13 @@ var AgentContextNextGen = class _AgentContextNextGen extends eventemitter3.Event
16238
16810
  ...piConfig
16239
16811
  }));
16240
16812
  }
16813
+ if (features.userInfo) {
16814
+ const uiConfig = configs.userInfo;
16815
+ this.registerPlugin(new UserInfoPluginNextGen({
16816
+ userId: this._userId,
16817
+ ...uiConfig
16818
+ }));
16819
+ }
16241
16820
  this.validateStrategyDependencies(this._compactionStrategy);
16242
16821
  }
16243
16822
  /**
@@ -22803,7 +23382,7 @@ init_constants();
22803
23382
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
22804
23383
  }
22805
23384
  try {
22806
- const content = await fs17.promises.readFile(configPath, "utf-8");
23385
+ const content = await fs18.promises.readFile(configPath, "utf-8");
22807
23386
  let config = JSON.parse(content);
22808
23387
  config = this.interpolateEnvVars(config);
22809
23388
  this.validate(config);
@@ -22824,8 +23403,8 @@ init_constants();
22824
23403
  throw new Error("Configuration file not found. Searched: " + this.DEFAULT_PATHS.join(", "));
22825
23404
  }
22826
23405
  try {
22827
- const fs18 = __require("fs");
22828
- const content = fs18.readFileSync(configPath, "utf-8");
23406
+ const fs19 = __require("fs");
23407
+ const content = fs19.readFileSync(configPath, "utf-8");
22829
23408
  let config = JSON.parse(content);
22830
23409
  config = this.interpolateEnvVars(config);
22831
23410
  this.validate(config);
@@ -22843,7 +23422,7 @@ init_constants();
22843
23422
  static async findConfig() {
22844
23423
  for (const path6 of this.DEFAULT_PATHS) {
22845
23424
  try {
22846
- await fs17.promises.access(path2.resolve(path6));
23425
+ await fs18.promises.access(path2.resolve(path6));
22847
23426
  return path2.resolve(path6);
22848
23427
  } catch {
22849
23428
  }
@@ -22854,10 +23433,10 @@ init_constants();
22854
23433
  * Find configuration file synchronously
22855
23434
  */
22856
23435
  static findConfigSync() {
22857
- const fs18 = __require("fs");
23436
+ const fs19 = __require("fs");
22858
23437
  for (const path6 of this.DEFAULT_PATHS) {
22859
23438
  try {
22860
- fs18.accessSync(path2.resolve(path6));
23439
+ fs19.accessSync(path2.resolve(path6));
22861
23440
  return path2.resolve(path6);
22862
23441
  } catch {
22863
23442
  }
@@ -28431,7 +29010,7 @@ var MCPRegistry = class {
28431
29010
  static async loadFromConfigFile(path6) {
28432
29011
  try {
28433
29012
  const configPath = path2.resolve(path6);
28434
- const content = await fs17.promises.readFile(configPath, "utf-8");
29013
+ const content = await fs18.promises.readFile(configPath, "utf-8");
28435
29014
  const config = JSON.parse(content);
28436
29015
  if (!config.mcp) {
28437
29016
  throw new MCPError("Configuration file does not contain MCP section");
@@ -29036,7 +29615,7 @@ var OpenAISTTProvider = class extends BaseMediaProvider {
29036
29615
  if (Buffer.isBuffer(audio)) {
29037
29616
  return new File([new Uint8Array(audio)], "audio.wav", { type: "audio/wav" });
29038
29617
  } else if (typeof audio === "string") {
29039
- return fs17__namespace.createReadStream(audio);
29618
+ return fs18__namespace.createReadStream(audio);
29040
29619
  } else {
29041
29620
  throw new Error("Invalid audio input: must be Buffer or file path");
29042
29621
  }
@@ -29589,7 +30168,7 @@ var TextToSpeech = class _TextToSpeech {
29589
30168
  */
29590
30169
  async toFile(text, filePath, options) {
29591
30170
  const response = await this.synthesize(text, options);
29592
- await fs16__namespace.writeFile(filePath, response.audio);
30171
+ await fs17__namespace.writeFile(filePath, response.audio);
29593
30172
  }
29594
30173
  // ======================== Introspection Methods ========================
29595
30174
  /**
@@ -29937,7 +30516,7 @@ var SpeechToText = class _SpeechToText {
29937
30516
  * @param options - Optional transcription parameters
29938
30517
  */
29939
30518
  async transcribeFile(filePath, options) {
29940
- const audio = await fs16__namespace.readFile(filePath);
30519
+ const audio = await fs17__namespace.readFile(filePath);
29941
30520
  return this.transcribe(audio, options);
29942
30521
  }
29943
30522
  /**
@@ -30263,7 +30842,7 @@ var OpenAIImageProvider = class extends BaseMediaProvider {
30263
30842
  if (Buffer.isBuffer(image)) {
30264
30843
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
30265
30844
  }
30266
- return fs17__namespace.createReadStream(image);
30845
+ return fs18__namespace.createReadStream(image);
30267
30846
  }
30268
30847
  /**
30269
30848
  * Handle OpenAI API errors
@@ -30410,8 +30989,8 @@ var GoogleImageProvider = class extends BaseMediaProvider {
30410
30989
  if (Buffer.isBuffer(image)) {
30411
30990
  imageBytes = image.toString("base64");
30412
30991
  } else {
30413
- const fs18 = await import('fs');
30414
- const buffer = fs18.readFileSync(image);
30992
+ const fs19 = await import('fs');
30993
+ const buffer = fs19.readFileSync(image);
30415
30994
  imageBytes = buffer.toString("base64");
30416
30995
  }
30417
30996
  return {
@@ -30572,7 +31151,7 @@ var GrokImageProvider = class extends BaseMediaProvider {
30572
31151
  if (Buffer.isBuffer(image)) {
30573
31152
  return new File([new Uint8Array(image)], "image.png", { type: "image/png" });
30574
31153
  }
30575
- return fs17__namespace.createReadStream(image);
31154
+ return fs18__namespace.createReadStream(image);
30576
31155
  }
30577
31156
  /**
30578
31157
  * Handle API errors
@@ -32022,8 +32601,8 @@ var OpenAISoraProvider = class extends BaseMediaProvider {
32022
32601
  return new File([new Uint8Array(image)], "input.png", { type: "image/png" });
32023
32602
  }
32024
32603
  if (!image.startsWith("http")) {
32025
- const fs18 = await import('fs');
32026
- const data = fs18.readFileSync(image);
32604
+ const fs19 = await import('fs');
32605
+ const data = fs19.readFileSync(image);
32027
32606
  return new File([new Uint8Array(data)], "input.png", { type: "image/png" });
32028
32607
  }
32029
32608
  const response = await fetch(image);
@@ -32201,7 +32780,7 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
32201
32780
  if (video.videoBytes) {
32202
32781
  buffer = Buffer.from(video.videoBytes, "base64");
32203
32782
  } else if (video.uri) {
32204
- const fs18 = await import('fs/promises');
32783
+ const fs19 = await import('fs/promises');
32205
32784
  const os3 = await import('os');
32206
32785
  const path6 = await import('path');
32207
32786
  const tempDir = os3.tmpdir();
@@ -32212,11 +32791,11 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
32212
32791
  // Pass as GeneratedVideo
32213
32792
  downloadPath: tempFile
32214
32793
  });
32215
- buffer = await fs18.readFile(tempFile);
32216
- await fs18.unlink(tempFile).catch(() => {
32794
+ buffer = await fs19.readFile(tempFile);
32795
+ await fs19.unlink(tempFile).catch(() => {
32217
32796
  });
32218
32797
  } catch (downloadError) {
32219
- await fs18.unlink(tempFile).catch(() => {
32798
+ await fs19.unlink(tempFile).catch(() => {
32220
32799
  });
32221
32800
  throw new ProviderError(
32222
32801
  "google",
@@ -32338,8 +32917,8 @@ var GoogleVeoProvider = class extends BaseMediaProvider {
32338
32917
  if (image.startsWith("http://") || image.startsWith("https://")) {
32339
32918
  return { imageUri: image };
32340
32919
  }
32341
- const fs18 = await import('fs/promises');
32342
- const data = await fs18.readFile(image);
32920
+ const fs19 = await import('fs/promises');
32921
+ const data = await fs19.readFile(image);
32343
32922
  return {
32344
32923
  imageBytes: data.toString("base64")
32345
32924
  };
@@ -32646,8 +33225,8 @@ var GrokImagineProvider = class extends BaseMediaProvider {
32646
33225
  if (image.startsWith("http") || image.startsWith("data:")) {
32647
33226
  return image;
32648
33227
  }
32649
- const fs18 = await import('fs');
32650
- const data = fs18.readFileSync(image);
33228
+ const fs19 = await import('fs');
33229
+ const data = fs19.readFileSync(image);
32651
33230
  const base64 = data.toString("base64");
32652
33231
  const ext = image.split(".").pop()?.toLowerCase() || "png";
32653
33232
  const mimeType = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : `image/${ext}`;
@@ -34083,7 +34662,7 @@ var DocumentReader = class _DocumentReader {
34083
34662
  async resolveSource(source) {
34084
34663
  switch (source.type) {
34085
34664
  case "file": {
34086
- const buffer = await fs16.readFile(source.path);
34665
+ const buffer = await fs17.readFile(source.path);
34087
34666
  const filename = source.path.split("/").pop() || source.path;
34088
34667
  return { buffer, filename };
34089
34668
  }
@@ -36350,7 +36929,7 @@ var InMemoryHistoryStorage = class {
36350
36929
  this.summaries = state.summaries ? [...state.summaries] : [];
36351
36930
  }
36352
36931
  };
36353
- function getDefaultBaseDirectory2() {
36932
+ function getDefaultBaseDirectory3() {
36354
36933
  const platform2 = process.platform;
36355
36934
  if (platform2 === "win32") {
36356
36935
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
@@ -36373,7 +36952,7 @@ var FileContextStorage = class {
36373
36952
  constructor(config) {
36374
36953
  this.agentId = config.agentId;
36375
36954
  const sanitizedAgentId = sanitizeId(config.agentId);
36376
- const baseDir = config.baseDirectory ?? getDefaultBaseDirectory2();
36955
+ const baseDir = config.baseDirectory ?? getDefaultBaseDirectory3();
36377
36956
  this.prettyPrint = config.prettyPrint ?? true;
36378
36957
  this.sessionsDirectory = path2.join(baseDir, sanitizedAgentId, "sessions");
36379
36958
  this.indexPath = path2.join(this.sessionsDirectory, "_index.json");
@@ -36402,11 +36981,11 @@ var FileContextStorage = class {
36402
36981
  const data = this.prettyPrint ? JSON.stringify(storedSession, null, 2) : JSON.stringify(storedSession);
36403
36982
  const tempPath = `${filePath}.tmp`;
36404
36983
  try {
36405
- await fs17.promises.writeFile(tempPath, data, "utf-8");
36406
- await fs17.promises.rename(tempPath, filePath);
36984
+ await fs18.promises.writeFile(tempPath, data, "utf-8");
36985
+ await fs18.promises.rename(tempPath, filePath);
36407
36986
  } catch (error) {
36408
36987
  try {
36409
- await fs17.promises.unlink(tempPath);
36988
+ await fs18.promises.unlink(tempPath);
36410
36989
  } catch {
36411
36990
  }
36412
36991
  throw error;
@@ -36427,7 +37006,7 @@ var FileContextStorage = class {
36427
37006
  const sanitizedSessionId = sanitizeId(sessionId);
36428
37007
  const filePath = this.getFilePath(sanitizedSessionId);
36429
37008
  try {
36430
- await fs17.promises.unlink(filePath);
37009
+ await fs18.promises.unlink(filePath);
36431
37010
  } catch (error) {
36432
37011
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
36433
37012
  throw error;
@@ -36442,7 +37021,7 @@ var FileContextStorage = class {
36442
37021
  const sanitizedSessionId = sanitizeId(sessionId);
36443
37022
  const filePath = this.getFilePath(sanitizedSessionId);
36444
37023
  try {
36445
- await fs17.promises.access(filePath);
37024
+ await fs18.promises.access(filePath);
36446
37025
  return true;
36447
37026
  } catch {
36448
37027
  return false;
@@ -36507,7 +37086,7 @@ var FileContextStorage = class {
36507
37086
  const sanitizedSessionId = sanitizeId(sessionId);
36508
37087
  const filePath = this.getFilePath(sanitizedSessionId);
36509
37088
  const data = this.prettyPrint ? JSON.stringify(stored, null, 2) : JSON.stringify(stored);
36510
- await fs17.promises.writeFile(filePath, data, "utf-8");
37089
+ await fs18.promises.writeFile(filePath, data, "utf-8");
36511
37090
  await this.updateIndex(stored);
36512
37091
  }
36513
37092
  /**
@@ -36535,13 +37114,13 @@ var FileContextStorage = class {
36535
37114
  */
36536
37115
  async rebuildIndex() {
36537
37116
  await this.ensureDirectory();
36538
- const files = await fs17.promises.readdir(this.sessionsDirectory);
37117
+ const files = await fs18.promises.readdir(this.sessionsDirectory);
36539
37118
  const sessionFiles = files.filter((f) => f.endsWith(".json") && !f.startsWith("_"));
36540
37119
  const entries = [];
36541
37120
  for (const file of sessionFiles) {
36542
37121
  try {
36543
37122
  const filePath = path2.join(this.sessionsDirectory, file);
36544
- const data = await fs17.promises.readFile(filePath, "utf-8");
37123
+ const data = await fs18.promises.readFile(filePath, "utf-8");
36545
37124
  const stored = JSON.parse(data);
36546
37125
  entries.push(this.storedToIndexEntry(stored));
36547
37126
  } catch {
@@ -36563,7 +37142,7 @@ var FileContextStorage = class {
36563
37142
  }
36564
37143
  async ensureDirectory() {
36565
37144
  try {
36566
- await fs17.promises.mkdir(this.sessionsDirectory, { recursive: true });
37145
+ await fs18.promises.mkdir(this.sessionsDirectory, { recursive: true });
36567
37146
  } catch (error) {
36568
37147
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
36569
37148
  throw error;
@@ -36573,7 +37152,7 @@ var FileContextStorage = class {
36573
37152
  async loadRaw(sanitizedSessionId) {
36574
37153
  const filePath = this.getFilePath(sanitizedSessionId);
36575
37154
  try {
36576
- const data = await fs17.promises.readFile(filePath, "utf-8");
37155
+ const data = await fs18.promises.readFile(filePath, "utf-8");
36577
37156
  return JSON.parse(data);
36578
37157
  } catch (error) {
36579
37158
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -36591,7 +37170,7 @@ var FileContextStorage = class {
36591
37170
  return this.index;
36592
37171
  }
36593
37172
  try {
36594
- const data = await fs17.promises.readFile(this.indexPath, "utf-8");
37173
+ const data = await fs18.promises.readFile(this.indexPath, "utf-8");
36595
37174
  this.index = JSON.parse(data);
36596
37175
  return this.index;
36597
37176
  } catch (error) {
@@ -36612,7 +37191,7 @@ var FileContextStorage = class {
36612
37191
  await this.ensureDirectory();
36613
37192
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
36614
37193
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
36615
- await fs17.promises.writeFile(this.indexPath, data, "utf-8");
37194
+ await fs18.promises.writeFile(this.indexPath, data, "utf-8");
36616
37195
  }
36617
37196
  async updateIndex(stored) {
36618
37197
  const index = await this.loadIndex();
@@ -36645,7 +37224,7 @@ var FileContextStorage = class {
36645
37224
  function createFileContextStorage(agentId, options) {
36646
37225
  return new FileContextStorage({ agentId, ...options });
36647
37226
  }
36648
- function getDefaultBaseDirectory3() {
37227
+ function getDefaultBaseDirectory4() {
36649
37228
  const platform2 = process.platform;
36650
37229
  if (platform2 === "win32") {
36651
37230
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
@@ -36664,7 +37243,7 @@ var FileAgentDefinitionStorage = class {
36664
37243
  prettyPrint;
36665
37244
  index = null;
36666
37245
  constructor(config = {}) {
36667
- this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory3();
37246
+ this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory4();
36668
37247
  this.prettyPrint = config.prettyPrint ?? true;
36669
37248
  this.indexPath = path2.join(this.baseDirectory, "_agents_index.json");
36670
37249
  }
@@ -36686,11 +37265,11 @@ var FileAgentDefinitionStorage = class {
36686
37265
  const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
36687
37266
  const tempPath = `${filePath}.tmp`;
36688
37267
  try {
36689
- await fs17.promises.writeFile(tempPath, data, "utf-8");
36690
- await fs17.promises.rename(tempPath, filePath);
37268
+ await fs18.promises.writeFile(tempPath, data, "utf-8");
37269
+ await fs18.promises.rename(tempPath, filePath);
36691
37270
  } catch (error) {
36692
37271
  try {
36693
- await fs17.promises.unlink(tempPath);
37272
+ await fs18.promises.unlink(tempPath);
36694
37273
  } catch {
36695
37274
  }
36696
37275
  throw error;
@@ -36712,7 +37291,7 @@ var FileAgentDefinitionStorage = class {
36712
37291
  const agentDir = path2.join(this.baseDirectory, sanitizedId);
36713
37292
  const filePath = path2.join(agentDir, "definition.json");
36714
37293
  try {
36715
- await fs17.promises.unlink(filePath);
37294
+ await fs18.promises.unlink(filePath);
36716
37295
  } catch (error) {
36717
37296
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
36718
37297
  throw error;
@@ -36727,7 +37306,7 @@ var FileAgentDefinitionStorage = class {
36727
37306
  const sanitizedId = sanitizeAgentId2(agentId);
36728
37307
  const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
36729
37308
  try {
36730
- await fs17.promises.access(filePath);
37309
+ await fs18.promises.access(filePath);
36731
37310
  return true;
36732
37311
  } catch {
36733
37312
  return false;
@@ -36789,13 +37368,13 @@ var FileAgentDefinitionStorage = class {
36789
37368
  */
36790
37369
  async rebuildIndex() {
36791
37370
  await this.ensureDirectory(this.baseDirectory);
36792
- const entries = await fs17.promises.readdir(this.baseDirectory, { withFileTypes: true });
37371
+ const entries = await fs18.promises.readdir(this.baseDirectory, { withFileTypes: true });
36793
37372
  const agentDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("_"));
36794
37373
  const indexEntries = [];
36795
37374
  for (const dir of agentDirs) {
36796
37375
  try {
36797
37376
  const filePath = path2.join(this.baseDirectory, dir.name, "definition.json");
36798
- const data = await fs17.promises.readFile(filePath, "utf-8");
37377
+ const data = await fs18.promises.readFile(filePath, "utf-8");
36799
37378
  const definition = JSON.parse(data);
36800
37379
  indexEntries.push(this.definitionToIndexEntry(definition));
36801
37380
  } catch {
@@ -36813,7 +37392,7 @@ var FileAgentDefinitionStorage = class {
36813
37392
  // ==========================================================================
36814
37393
  async ensureDirectory(dir) {
36815
37394
  try {
36816
- await fs17.promises.mkdir(dir, { recursive: true });
37395
+ await fs18.promises.mkdir(dir, { recursive: true });
36817
37396
  } catch (error) {
36818
37397
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
36819
37398
  throw error;
@@ -36823,7 +37402,7 @@ var FileAgentDefinitionStorage = class {
36823
37402
  async loadRaw(sanitizedId) {
36824
37403
  const filePath = path2.join(this.baseDirectory, sanitizedId, "definition.json");
36825
37404
  try {
36826
- const data = await fs17.promises.readFile(filePath, "utf-8");
37405
+ const data = await fs18.promises.readFile(filePath, "utf-8");
36827
37406
  return JSON.parse(data);
36828
37407
  } catch (error) {
36829
37408
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -36841,7 +37420,7 @@ var FileAgentDefinitionStorage = class {
36841
37420
  return this.index;
36842
37421
  }
36843
37422
  try {
36844
- const data = await fs17.promises.readFile(this.indexPath, "utf-8");
37423
+ const data = await fs18.promises.readFile(this.indexPath, "utf-8");
36845
37424
  this.index = JSON.parse(data);
36846
37425
  return this.index;
36847
37426
  } catch (error) {
@@ -36861,7 +37440,7 @@ var FileAgentDefinitionStorage = class {
36861
37440
  await this.ensureDirectory(this.baseDirectory);
36862
37441
  this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
36863
37442
  const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
36864
- await fs17.promises.writeFile(this.indexPath, data, "utf-8");
37443
+ await fs18.promises.writeFile(this.indexPath, data, "utf-8");
36865
37444
  }
36866
37445
  async updateIndex(definition) {
36867
37446
  const index = await this.loadIndex();
@@ -36919,10 +37498,10 @@ var FileMediaStorage = class {
36919
37498
  }
36920
37499
  async save(data, metadata) {
36921
37500
  const dir = metadata.userId ? path2__namespace.join(this.outputDir, metadata.userId) : this.outputDir;
36922
- await fs16__namespace.mkdir(dir, { recursive: true });
37501
+ await fs17__namespace.mkdir(dir, { recursive: true });
36923
37502
  const filename = metadata.suggestedFilename ?? this.generateFilename(metadata);
36924
37503
  const filePath = path2__namespace.join(dir, filename);
36925
- await fs16__namespace.writeFile(filePath, data);
37504
+ await fs17__namespace.writeFile(filePath, data);
36926
37505
  const format = metadata.format.toLowerCase();
36927
37506
  const mimeType = MIME_TYPES2[format] ?? "application/octet-stream";
36928
37507
  return {
@@ -36933,7 +37512,7 @@ var FileMediaStorage = class {
36933
37512
  }
36934
37513
  async read(location) {
36935
37514
  try {
36936
- return await fs16__namespace.readFile(location);
37515
+ return await fs17__namespace.readFile(location);
36937
37516
  } catch (err) {
36938
37517
  if (err.code === "ENOENT") {
36939
37518
  return null;
@@ -36943,7 +37522,7 @@ var FileMediaStorage = class {
36943
37522
  }
36944
37523
  async delete(location) {
36945
37524
  try {
36946
- await fs16__namespace.unlink(location);
37525
+ await fs17__namespace.unlink(location);
36947
37526
  } catch (err) {
36948
37527
  if (err.code === "ENOENT") {
36949
37528
  return;
@@ -36953,7 +37532,7 @@ var FileMediaStorage = class {
36953
37532
  }
36954
37533
  async exists(location) {
36955
37534
  try {
36956
- await fs16__namespace.access(location);
37535
+ await fs17__namespace.access(location);
36957
37536
  return true;
36958
37537
  } catch {
36959
37538
  return false;
@@ -36962,11 +37541,11 @@ var FileMediaStorage = class {
36962
37541
  async list(options) {
36963
37542
  await this.ensureDir();
36964
37543
  let entries = [];
36965
- const files = await fs16__namespace.readdir(this.outputDir);
37544
+ const files = await fs17__namespace.readdir(this.outputDir);
36966
37545
  for (const file of files) {
36967
37546
  const filePath = path2__namespace.join(this.outputDir, file);
36968
37547
  try {
36969
- const stat6 = await fs16__namespace.stat(filePath);
37548
+ const stat6 = await fs17__namespace.stat(filePath);
36970
37549
  if (!stat6.isFile()) continue;
36971
37550
  const ext = path2__namespace.extname(file).slice(1).toLowerCase();
36972
37551
  const mimeType = MIME_TYPES2[ext] ?? "application/octet-stream";
@@ -37006,7 +37585,7 @@ var FileMediaStorage = class {
37006
37585
  }
37007
37586
  async ensureDir() {
37008
37587
  if (!this.initialized) {
37009
- await fs16__namespace.mkdir(this.outputDir, { recursive: true });
37588
+ await fs17__namespace.mkdir(this.outputDir, { recursive: true });
37010
37589
  this.initialized = true;
37011
37590
  }
37012
37591
  }
@@ -37014,58 +37593,82 @@ var FileMediaStorage = class {
37014
37593
  function createFileMediaStorage(config) {
37015
37594
  return new FileMediaStorage(config);
37016
37595
  }
37017
- function getDefaultBaseDirectory4() {
37596
+ function getDefaultBaseDirectory5() {
37018
37597
  const platform2 = process.platform;
37019
37598
  if (platform2 === "win32") {
37020
37599
  const appData = process.env.APPDATA || process.env.LOCALAPPDATA;
37021
37600
  if (appData) {
37022
- return path2.join(appData, "oneringai", "custom-tools");
37601
+ return path2.join(appData, "oneringai", "users");
37023
37602
  }
37024
37603
  }
37025
- return path2.join(os2.homedir(), ".oneringai", "custom-tools");
37604
+ return path2.join(os2.homedir(), ".oneringai", "users");
37605
+ }
37606
+ var DEFAULT_USER_ID2 = "default";
37607
+ function sanitizeUserId2(userId) {
37608
+ if (!userId) {
37609
+ return DEFAULT_USER_ID2;
37610
+ }
37611
+ return userId.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || DEFAULT_USER_ID2;
37026
37612
  }
37027
37613
  function sanitizeName(name) {
37028
37614
  return name.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "").toLowerCase() || "default";
37029
37615
  }
37030
37616
  var FileCustomToolStorage = class {
37031
37617
  baseDirectory;
37032
- indexPath;
37033
37618
  prettyPrint;
37034
- index = null;
37035
37619
  constructor(config = {}) {
37036
- this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory4();
37620
+ this.baseDirectory = config.baseDirectory ?? getDefaultBaseDirectory5();
37037
37621
  this.prettyPrint = config.prettyPrint ?? true;
37038
- this.indexPath = path2.join(this.baseDirectory, "_index.json");
37622
+ }
37623
+ /**
37624
+ * Get the directory path for a specific user's custom tools
37625
+ */
37626
+ getUserDirectory(userId) {
37627
+ const sanitizedId = sanitizeUserId2(userId);
37628
+ return path2.join(this.baseDirectory, sanitizedId, "custom-tools");
37629
+ }
37630
+ /**
37631
+ * Get the index file path for a specific user
37632
+ */
37633
+ getUserIndexPath(userId) {
37634
+ return path2.join(this.getUserDirectory(userId), "_index.json");
37635
+ }
37636
+ /**
37637
+ * Get the tool file path for a specific user
37638
+ */
37639
+ getToolPath(userId, sanitizedName) {
37640
+ return path2.join(this.getUserDirectory(userId), `${sanitizedName}.json`);
37039
37641
  }
37040
37642
  /**
37041
37643
  * Save a custom tool definition
37042
37644
  */
37043
- async save(definition) {
37645
+ async save(userId, definition) {
37646
+ const directory = this.getUserDirectory(userId);
37044
37647
  const sanitized = sanitizeName(definition.name);
37045
- const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
37046
- await this.ensureDirectory(this.baseDirectory);
37648
+ const filePath = this.getToolPath(userId, sanitized);
37649
+ await this.ensureDirectory(directory);
37047
37650
  const data = this.prettyPrint ? JSON.stringify(definition, null, 2) : JSON.stringify(definition);
37048
37651
  const tempPath = `${filePath}.tmp`;
37049
37652
  try {
37050
- await fs17.promises.writeFile(tempPath, data, "utf-8");
37051
- await fs17.promises.rename(tempPath, filePath);
37653
+ await fs18.promises.writeFile(tempPath, data, "utf-8");
37654
+ await fs18.promises.rename(tempPath, filePath);
37052
37655
  } catch (error) {
37053
37656
  try {
37054
- await fs17.promises.unlink(tempPath);
37657
+ await fs18.promises.unlink(tempPath);
37055
37658
  } catch {
37056
37659
  }
37057
37660
  throw error;
37058
37661
  }
37059
- await this.updateIndex(definition);
37662
+ await this.updateIndex(userId, definition);
37060
37663
  }
37061
37664
  /**
37062
37665
  * Load a custom tool definition by name
37063
37666
  */
37064
- async load(name) {
37667
+ async load(userId, name) {
37065
37668
  const sanitized = sanitizeName(name);
37066
- const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
37669
+ const filePath = this.getToolPath(userId, sanitized);
37067
37670
  try {
37068
- const data = await fs17.promises.readFile(filePath, "utf-8");
37671
+ const data = await fs18.promises.readFile(filePath, "utf-8");
37069
37672
  return JSON.parse(data);
37070
37673
  } catch (error) {
37071
37674
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -37080,26 +37683,26 @@ var FileCustomToolStorage = class {
37080
37683
  /**
37081
37684
  * Delete a custom tool definition
37082
37685
  */
37083
- async delete(name) {
37686
+ async delete(userId, name) {
37084
37687
  const sanitized = sanitizeName(name);
37085
- const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
37688
+ const filePath = this.getToolPath(userId, sanitized);
37086
37689
  try {
37087
- await fs17.promises.unlink(filePath);
37690
+ await fs18.promises.unlink(filePath);
37088
37691
  } catch (error) {
37089
37692
  if (error instanceof Error && "code" in error && error.code !== "ENOENT") {
37090
37693
  throw error;
37091
37694
  }
37092
37695
  }
37093
- await this.removeFromIndex(name);
37696
+ await this.removeFromIndex(userId, name);
37094
37697
  }
37095
37698
  /**
37096
37699
  * Check if a custom tool exists
37097
37700
  */
37098
- async exists(name) {
37701
+ async exists(userId, name) {
37099
37702
  const sanitized = sanitizeName(name);
37100
- const filePath = path2.join(this.baseDirectory, `${sanitized}.json`);
37703
+ const filePath = this.getToolPath(userId, sanitized);
37101
37704
  try {
37102
- await fs17.promises.access(filePath);
37705
+ await fs18.promises.access(filePath);
37103
37706
  return true;
37104
37707
  } catch {
37105
37708
  return false;
@@ -37108,8 +37711,8 @@ var FileCustomToolStorage = class {
37108
37711
  /**
37109
37712
  * List custom tools (summaries only)
37110
37713
  */
37111
- async list(options) {
37112
- const index = await this.loadIndex();
37714
+ async list(userId, options) {
37715
+ const index = await this.loadIndex(userId);
37113
37716
  let entries = [...index.tools];
37114
37717
  if (options?.tags && options.tags.length > 0) {
37115
37718
  entries = entries.filter((e) => {
@@ -37150,62 +37753,59 @@ var FileCustomToolStorage = class {
37150
37753
  /**
37151
37754
  * Update metadata without loading full definition
37152
37755
  */
37153
- async updateMetadata(name, metadata) {
37154
- const definition = await this.load(name);
37756
+ async updateMetadata(userId, name, metadata) {
37757
+ const definition = await this.load(userId, name);
37155
37758
  if (!definition) {
37156
37759
  throw new Error(`Custom tool '${name}' not found`);
37157
37760
  }
37158
37761
  definition.metadata = { ...definition.metadata, ...metadata };
37159
37762
  definition.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
37160
- await this.save(definition);
37763
+ await this.save(userId, definition);
37161
37764
  }
37162
37765
  /**
37163
- * Get storage path
37766
+ * Get storage path for a specific user
37164
37767
  */
37165
- getPath() {
37166
- return this.baseDirectory;
37768
+ getPath(userId) {
37769
+ return this.getUserDirectory(userId);
37167
37770
  }
37168
37771
  // ==========================================================================
37169
37772
  // Private Helpers
37170
37773
  // ==========================================================================
37171
37774
  async ensureDirectory(dir) {
37172
37775
  try {
37173
- await fs17.promises.mkdir(dir, { recursive: true });
37776
+ await fs18.promises.mkdir(dir, { recursive: true });
37174
37777
  } catch (error) {
37175
37778
  if (error instanceof Error && "code" in error && error.code !== "EEXIST") {
37176
37779
  throw error;
37177
37780
  }
37178
37781
  }
37179
37782
  }
37180
- async loadIndex() {
37181
- if (this.index) {
37182
- return this.index;
37183
- }
37783
+ async loadIndex(userId) {
37784
+ const indexPath = this.getUserIndexPath(userId);
37184
37785
  try {
37185
- const data = await fs17.promises.readFile(this.indexPath, "utf-8");
37186
- this.index = JSON.parse(data);
37187
- return this.index;
37786
+ const data = await fs18.promises.readFile(indexPath, "utf-8");
37787
+ return JSON.parse(data);
37188
37788
  } catch (error) {
37189
37789
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
37190
- this.index = {
37790
+ return {
37191
37791
  version: 1,
37192
37792
  tools: [],
37193
37793
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
37194
37794
  };
37195
- return this.index;
37196
37795
  }
37197
37796
  throw error;
37198
37797
  }
37199
37798
  }
37200
- async saveIndex() {
37201
- if (!this.index) return;
37202
- await this.ensureDirectory(this.baseDirectory);
37203
- this.index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
37204
- const data = this.prettyPrint ? JSON.stringify(this.index, null, 2) : JSON.stringify(this.index);
37205
- await fs17.promises.writeFile(this.indexPath, data, "utf-8");
37799
+ async saveIndex(userId, index) {
37800
+ const directory = this.getUserDirectory(userId);
37801
+ const indexPath = this.getUserIndexPath(userId);
37802
+ await this.ensureDirectory(directory);
37803
+ index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
37804
+ const data = this.prettyPrint ? JSON.stringify(index, null, 2) : JSON.stringify(index);
37805
+ await fs18.promises.writeFile(indexPath, data, "utf-8");
37206
37806
  }
37207
- async updateIndex(definition) {
37208
- const index = await this.loadIndex();
37807
+ async updateIndex(userId, definition) {
37808
+ const index = await this.loadIndex(userId);
37209
37809
  const entry = this.definitionToIndexEntry(definition);
37210
37810
  const existingIdx = index.tools.findIndex((e) => e.name === definition.name);
37211
37811
  if (existingIdx >= 0) {
@@ -37213,12 +37813,12 @@ var FileCustomToolStorage = class {
37213
37813
  } else {
37214
37814
  index.tools.push(entry);
37215
37815
  }
37216
- await this.saveIndex();
37816
+ await this.saveIndex(userId, index);
37217
37817
  }
37218
- async removeFromIndex(name) {
37219
- const index = await this.loadIndex();
37818
+ async removeFromIndex(userId, name) {
37819
+ const index = await this.loadIndex(userId);
37220
37820
  index.tools = index.tools.filter((e) => e.name !== name);
37221
- await this.saveIndex();
37821
+ await this.saveIndex(userId, index);
37222
37822
  }
37223
37823
  definitionToIndexEntry(definition) {
37224
37824
  return {
@@ -38335,8 +38935,8 @@ var FileStorage = class {
38335
38935
  }
38336
38936
  async ensureDirectory() {
38337
38937
  try {
38338
- await fs16__namespace.mkdir(this.directory, { recursive: true });
38339
- await fs16__namespace.chmod(this.directory, 448);
38938
+ await fs17__namespace.mkdir(this.directory, { recursive: true });
38939
+ await fs17__namespace.chmod(this.directory, 448);
38340
38940
  } catch (error) {
38341
38941
  }
38342
38942
  }
@@ -38352,13 +38952,13 @@ var FileStorage = class {
38352
38952
  const filePath = this.getFilePath(key);
38353
38953
  const plaintext = JSON.stringify(token);
38354
38954
  const encrypted = encrypt(plaintext, this.encryptionKey);
38355
- await fs16__namespace.writeFile(filePath, encrypted, "utf8");
38356
- await fs16__namespace.chmod(filePath, 384);
38955
+ await fs17__namespace.writeFile(filePath, encrypted, "utf8");
38956
+ await fs17__namespace.chmod(filePath, 384);
38357
38957
  }
38358
38958
  async getToken(key) {
38359
38959
  const filePath = this.getFilePath(key);
38360
38960
  try {
38361
- const encrypted = await fs16__namespace.readFile(filePath, "utf8");
38961
+ const encrypted = await fs17__namespace.readFile(filePath, "utf8");
38362
38962
  const decrypted = decrypt(encrypted, this.encryptionKey);
38363
38963
  return JSON.parse(decrypted);
38364
38964
  } catch (error) {
@@ -38367,7 +38967,7 @@ var FileStorage = class {
38367
38967
  }
38368
38968
  console.error("Failed to read/decrypt token file:", error);
38369
38969
  try {
38370
- await fs16__namespace.unlink(filePath);
38970
+ await fs17__namespace.unlink(filePath);
38371
38971
  } catch {
38372
38972
  }
38373
38973
  return null;
@@ -38376,7 +38976,7 @@ var FileStorage = class {
38376
38976
  async deleteToken(key) {
38377
38977
  const filePath = this.getFilePath(key);
38378
38978
  try {
38379
- await fs16__namespace.unlink(filePath);
38979
+ await fs17__namespace.unlink(filePath);
38380
38980
  } catch (error) {
38381
38981
  if (error.code !== "ENOENT") {
38382
38982
  throw error;
@@ -38386,7 +38986,7 @@ var FileStorage = class {
38386
38986
  async hasToken(key) {
38387
38987
  const filePath = this.getFilePath(key);
38388
38988
  try {
38389
- await fs16__namespace.access(filePath);
38989
+ await fs17__namespace.access(filePath);
38390
38990
  return true;
38391
38991
  } catch {
38392
38992
  return false;
@@ -38397,7 +38997,7 @@ var FileStorage = class {
38397
38997
  */
38398
38998
  async listTokens() {
38399
38999
  try {
38400
- const files = await fs16__namespace.readdir(this.directory);
39000
+ const files = await fs17__namespace.readdir(this.directory);
38401
39001
  return files.filter((f) => f.endsWith(".token")).map((f) => f.replace(".token", ""));
38402
39002
  } catch {
38403
39003
  return [];
@@ -38408,10 +39008,10 @@ var FileStorage = class {
38408
39008
  */
38409
39009
  async clearAll() {
38410
39010
  try {
38411
- const files = await fs16__namespace.readdir(this.directory);
39011
+ const files = await fs17__namespace.readdir(this.directory);
38412
39012
  const tokenFiles = files.filter((f) => f.endsWith(".token"));
38413
39013
  await Promise.all(
38414
- tokenFiles.map((f) => fs16__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
39014
+ tokenFiles.map((f) => fs17__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
38415
39015
  }))
38416
39016
  );
38417
39017
  } catch {
@@ -38859,14 +39459,14 @@ var FileConnectorStorage = class {
38859
39459
  await this.ensureDirectory();
38860
39460
  const filePath = this.getFilePath(name);
38861
39461
  const json = JSON.stringify(stored, null, 2);
38862
- await fs16__namespace.writeFile(filePath, json, "utf8");
38863
- await fs16__namespace.chmod(filePath, 384);
39462
+ await fs17__namespace.writeFile(filePath, json, "utf8");
39463
+ await fs17__namespace.chmod(filePath, 384);
38864
39464
  await this.updateIndex(name, "add");
38865
39465
  }
38866
39466
  async get(name) {
38867
39467
  const filePath = this.getFilePath(name);
38868
39468
  try {
38869
- const json = await fs16__namespace.readFile(filePath, "utf8");
39469
+ const json = await fs17__namespace.readFile(filePath, "utf8");
38870
39470
  return JSON.parse(json);
38871
39471
  } catch (error) {
38872
39472
  const err = error;
@@ -38879,7 +39479,7 @@ var FileConnectorStorage = class {
38879
39479
  async delete(name) {
38880
39480
  const filePath = this.getFilePath(name);
38881
39481
  try {
38882
- await fs16__namespace.unlink(filePath);
39482
+ await fs17__namespace.unlink(filePath);
38883
39483
  await this.updateIndex(name, "remove");
38884
39484
  return true;
38885
39485
  } catch (error) {
@@ -38893,7 +39493,7 @@ var FileConnectorStorage = class {
38893
39493
  async has(name) {
38894
39494
  const filePath = this.getFilePath(name);
38895
39495
  try {
38896
- await fs16__namespace.access(filePath);
39496
+ await fs17__namespace.access(filePath);
38897
39497
  return true;
38898
39498
  } catch {
38899
39499
  return false;
@@ -38919,13 +39519,13 @@ var FileConnectorStorage = class {
38919
39519
  */
38920
39520
  async clear() {
38921
39521
  try {
38922
- const files = await fs16__namespace.readdir(this.directory);
39522
+ const files = await fs17__namespace.readdir(this.directory);
38923
39523
  const connectorFiles = files.filter(
38924
39524
  (f) => f.endsWith(".connector.json") || f === "_index.json"
38925
39525
  );
38926
39526
  await Promise.all(
38927
39527
  connectorFiles.map(
38928
- (f) => fs16__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
39528
+ (f) => fs17__namespace.unlink(path2__namespace.join(this.directory, f)).catch(() => {
38929
39529
  })
38930
39530
  )
38931
39531
  );
@@ -38952,8 +39552,8 @@ var FileConnectorStorage = class {
38952
39552
  async ensureDirectory() {
38953
39553
  if (this.initialized) return;
38954
39554
  try {
38955
- await fs16__namespace.mkdir(this.directory, { recursive: true });
38956
- await fs16__namespace.chmod(this.directory, 448);
39555
+ await fs17__namespace.mkdir(this.directory, { recursive: true });
39556
+ await fs17__namespace.chmod(this.directory, 448);
38957
39557
  this.initialized = true;
38958
39558
  } catch {
38959
39559
  this.initialized = true;
@@ -38964,7 +39564,7 @@ var FileConnectorStorage = class {
38964
39564
  */
38965
39565
  async loadIndex() {
38966
39566
  try {
38967
- const json = await fs16__namespace.readFile(this.indexPath, "utf8");
39567
+ const json = await fs17__namespace.readFile(this.indexPath, "utf8");
38968
39568
  return JSON.parse(json);
38969
39569
  } catch {
38970
39570
  return { connectors: {} };
@@ -38982,8 +39582,8 @@ var FileConnectorStorage = class {
38982
39582
  delete index.connectors[hash];
38983
39583
  }
38984
39584
  const json = JSON.stringify(index, null, 2);
38985
- await fs16__namespace.writeFile(this.indexPath, json, "utf8");
38986
- await fs16__namespace.chmod(this.indexPath, 384);
39585
+ await fs17__namespace.writeFile(this.indexPath, json, "utf8");
39586
+ await fs17__namespace.chmod(this.indexPath, 384);
38987
39587
  }
38988
39588
  };
38989
39589
 
@@ -41438,8 +42038,8 @@ function createMessageWithImages(text, imageUrls, role = "user" /* USER */) {
41438
42038
  var execAsync = util.promisify(child_process.exec);
41439
42039
  function cleanupTempFile(filePath) {
41440
42040
  try {
41441
- if (fs17__namespace.existsSync(filePath)) {
41442
- fs17__namespace.unlinkSync(filePath);
42041
+ if (fs18__namespace.existsSync(filePath)) {
42042
+ fs18__namespace.unlinkSync(filePath);
41443
42043
  }
41444
42044
  } catch {
41445
42045
  }
@@ -41490,7 +42090,7 @@ async function readClipboardImageMac() {
41490
42090
  end try
41491
42091
  `;
41492
42092
  const { stdout } = await execAsync(`osascript -e '${script}'`);
41493
- if (stdout.includes("success") || fs17__namespace.existsSync(tempFile)) {
42093
+ if (stdout.includes("success") || fs18__namespace.existsSync(tempFile)) {
41494
42094
  return await convertFileToDataUri(tempFile);
41495
42095
  }
41496
42096
  return {
@@ -41507,14 +42107,14 @@ async function readClipboardImageLinux() {
41507
42107
  try {
41508
42108
  try {
41509
42109
  await execAsync(`xclip -selection clipboard -t image/png -o > "${tempFile}"`);
41510
- if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
42110
+ if (fs18__namespace.existsSync(tempFile) && fs18__namespace.statSync(tempFile).size > 0) {
41511
42111
  return await convertFileToDataUri(tempFile);
41512
42112
  }
41513
42113
  } catch {
41514
42114
  }
41515
42115
  try {
41516
42116
  await execAsync(`wl-paste -t image/png > "${tempFile}"`);
41517
- if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
42117
+ if (fs18__namespace.existsSync(tempFile) && fs18__namespace.statSync(tempFile).size > 0) {
41518
42118
  return await convertFileToDataUri(tempFile);
41519
42119
  }
41520
42120
  } catch {
@@ -41541,7 +42141,7 @@ async function readClipboardImageWindows() {
41541
42141
  }
41542
42142
  `;
41543
42143
  await execAsync(`powershell -Command "${psScript}"`);
41544
- if (fs17__namespace.existsSync(tempFile) && fs17__namespace.statSync(tempFile).size > 0) {
42144
+ if (fs18__namespace.existsSync(tempFile) && fs18__namespace.statSync(tempFile).size > 0) {
41545
42145
  return await convertFileToDataUri(tempFile);
41546
42146
  }
41547
42147
  return {
@@ -41554,7 +42154,7 @@ async function readClipboardImageWindows() {
41554
42154
  }
41555
42155
  async function convertFileToDataUri(filePath) {
41556
42156
  try {
41557
- const imageBuffer = fs17__namespace.readFileSync(filePath);
42157
+ const imageBuffer = fs18__namespace.readFileSync(filePath);
41558
42158
  const base64Image = imageBuffer.toString("base64");
41559
42159
  const magic = imageBuffer.slice(0, 4).toString("hex");
41560
42160
  let mimeType = "image/png";
@@ -42103,7 +42703,7 @@ EXAMPLES:
42103
42703
  };
42104
42704
  }
42105
42705
  const resolvedPath = validation.resolvedPath;
42106
- if (!fs17.existsSync(resolvedPath)) {
42706
+ if (!fs18.existsSync(resolvedPath)) {
42107
42707
  return {
42108
42708
  success: false,
42109
42709
  error: `File not found: ${file_path}`,
@@ -42111,7 +42711,7 @@ EXAMPLES:
42111
42711
  };
42112
42712
  }
42113
42713
  try {
42114
- const stats = await fs16.stat(resolvedPath);
42714
+ const stats = await fs17.stat(resolvedPath);
42115
42715
  if (!stats.isFile()) {
42116
42716
  return {
42117
42717
  success: false,
@@ -42153,7 +42753,7 @@ EXAMPLES:
42153
42753
  } catch {
42154
42754
  }
42155
42755
  }
42156
- const content = await fs16.readFile(resolvedPath, "utf-8");
42756
+ const content = await fs17.readFile(resolvedPath, "utf-8");
42157
42757
  const allLines = content.split("\n");
42158
42758
  const totalLines = allLines.length;
42159
42759
  const startIndex = Math.max(0, offset - 1);
@@ -42258,13 +42858,13 @@ EXAMPLES:
42258
42858
  };
42259
42859
  }
42260
42860
  const resolvedPath = validation.resolvedPath;
42261
- const fileExists = fs17.existsSync(resolvedPath);
42861
+ const fileExists = fs18.existsSync(resolvedPath);
42262
42862
  try {
42263
42863
  const parentDir = path2.dirname(resolvedPath);
42264
- if (!fs17.existsSync(parentDir)) {
42265
- await fs16.mkdir(parentDir, { recursive: true });
42864
+ if (!fs18.existsSync(parentDir)) {
42865
+ await fs17.mkdir(parentDir, { recursive: true });
42266
42866
  }
42267
- await fs16.writeFile(resolvedPath, content, "utf-8");
42867
+ await fs17.writeFile(resolvedPath, content, "utf-8");
42268
42868
  return {
42269
42869
  success: true,
42270
42870
  path: file_path,
@@ -42367,7 +42967,7 @@ EXAMPLES:
42367
42967
  };
42368
42968
  }
42369
42969
  const resolvedPath = validation.resolvedPath;
42370
- if (!fs17.existsSync(resolvedPath)) {
42970
+ if (!fs18.existsSync(resolvedPath)) {
42371
42971
  return {
42372
42972
  success: false,
42373
42973
  error: `File not found: ${file_path}`,
@@ -42375,7 +42975,7 @@ EXAMPLES:
42375
42975
  };
42376
42976
  }
42377
42977
  try {
42378
- const content = await fs16.readFile(resolvedPath, "utf-8");
42978
+ const content = await fs17.readFile(resolvedPath, "utf-8");
42379
42979
  let occurrences = 0;
42380
42980
  let searchIndex = 0;
42381
42981
  while (true) {
@@ -42414,7 +43014,7 @@ EXAMPLES:
42414
43014
  } else {
42415
43015
  newContent = content.replace(old_string, new_string);
42416
43016
  }
42417
- await fs16.writeFile(resolvedPath, newContent, "utf-8");
43017
+ await fs17.writeFile(resolvedPath, newContent, "utf-8");
42418
43018
  const diffPreview = generateDiffPreview(old_string, new_string);
42419
43019
  return {
42420
43020
  success: true,
@@ -42470,7 +43070,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
42470
43070
  return results;
42471
43071
  }
42472
43072
  try {
42473
- const entries = await fs16.readdir(dir, { withFileTypes: true });
43073
+ const entries = await fs17.readdir(dir, { withFileTypes: true });
42474
43074
  for (const entry of entries) {
42475
43075
  if (results.length >= config.maxResults) break;
42476
43076
  const fullPath = path2.join(dir, entry.name);
@@ -42484,7 +43084,7 @@ async function findFiles(dir, pattern, baseDir, config, results = [], depth = 0)
42484
43084
  } else if (entry.isFile()) {
42485
43085
  if (matchGlobPattern(pattern, relativePath)) {
42486
43086
  try {
42487
- const stats = await fs16.stat(fullPath);
43087
+ const stats = await fs17.stat(fullPath);
42488
43088
  results.push({
42489
43089
  path: relativePath,
42490
43090
  mtime: stats.mtimeMs
@@ -42566,7 +43166,7 @@ WHEN TO USE:
42566
43166
  };
42567
43167
  }
42568
43168
  const resolvedDir = validation.resolvedPath;
42569
- if (!fs17.existsSync(resolvedDir)) {
43169
+ if (!fs18.existsSync(resolvedDir)) {
42570
43170
  return {
42571
43171
  success: false,
42572
43172
  error: `Directory not found: ${searchDir}`
@@ -42621,7 +43221,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
42621
43221
  return files;
42622
43222
  }
42623
43223
  try {
42624
- const entries = await fs16.readdir(dir, { withFileTypes: true });
43224
+ const entries = await fs17.readdir(dir, { withFileTypes: true });
42625
43225
  for (const entry of entries) {
42626
43226
  const fullPath = path2.join(dir, entry.name);
42627
43227
  if (entry.isDirectory()) {
@@ -42654,7 +43254,7 @@ async function findFilesToSearch(dir, baseDir, config, globPattern, fileType, fi
42654
43254
  async function searchFile(filePath, regex, contextBefore, contextAfter) {
42655
43255
  const matches = [];
42656
43256
  try {
42657
- const content = await fs16.readFile(filePath, "utf-8");
43257
+ const content = await fs17.readFile(filePath, "utf-8");
42658
43258
  const lines = content.split("\n");
42659
43259
  for (let i = 0; i < lines.length; i++) {
42660
43260
  const line = lines[i] ?? "";
@@ -42795,7 +43395,7 @@ WHEN TO USE:
42795
43395
  };
42796
43396
  }
42797
43397
  const resolvedPath = validation.resolvedPath;
42798
- if (!fs17.existsSync(resolvedPath)) {
43398
+ if (!fs18.existsSync(resolvedPath)) {
42799
43399
  return {
42800
43400
  success: false,
42801
43401
  error: `Path not found: ${searchPath}`
@@ -42811,7 +43411,7 @@ WHEN TO USE:
42811
43411
  };
42812
43412
  }
42813
43413
  try {
42814
- const stats = await fs16.stat(resolvedPath);
43414
+ const stats = await fs17.stat(resolvedPath);
42815
43415
  let filesToSearch;
42816
43416
  if (stats.isFile()) {
42817
43417
  filesToSearch = [resolvedPath];
@@ -42899,7 +43499,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
42899
43499
  return entries;
42900
43500
  }
42901
43501
  try {
42902
- const dirEntries = await fs16.readdir(dir, { withFileTypes: true });
43502
+ const dirEntries = await fs17.readdir(dir, { withFileTypes: true });
42903
43503
  for (const entry of dirEntries) {
42904
43504
  if (entries.length >= config.maxResults) break;
42905
43505
  const fullPath = path2.join(dir, entry.name);
@@ -42917,7 +43517,7 @@ async function listDir(dir, baseDir, config, recursive, filter, maxDepth = 3, cu
42917
43517
  }
42918
43518
  if (filter === "directories" && !isDir) continue;
42919
43519
  try {
42920
- const stats = await fs16.stat(fullPath);
43520
+ const stats = await fs17.stat(fullPath);
42921
43521
  const dirEntry = {
42922
43522
  name: entry.name,
42923
43523
  path: relativePath,
@@ -43013,14 +43613,14 @@ EXAMPLES:
43013
43613
  };
43014
43614
  }
43015
43615
  const resolvedPath = validation.resolvedPath;
43016
- if (!fs17.existsSync(resolvedPath)) {
43616
+ if (!fs18.existsSync(resolvedPath)) {
43017
43617
  return {
43018
43618
  success: false,
43019
43619
  error: `Directory not found: ${path6}`
43020
43620
  };
43021
43621
  }
43022
43622
  try {
43023
- const stats = await fs16.stat(resolvedPath);
43623
+ const stats = await fs17.stat(resolvedPath);
43024
43624
  if (!stats.isDirectory()) {
43025
43625
  return {
43026
43626
  success: false,
@@ -46789,7 +47389,7 @@ var desktopTools = [
46789
47389
 
46790
47390
  // src/tools/custom-tools/resolveStorage.ts
46791
47391
  init_StorageRegistry();
46792
- function buildStorageContext(toolContext) {
47392
+ function buildStorageContext2(toolContext) {
46793
47393
  const global2 = exports.StorageRegistry.getContext();
46794
47394
  if (global2) return global2;
46795
47395
  if (toolContext?.userId) return { userId: toolContext.userId };
@@ -46799,7 +47399,7 @@ function resolveCustomToolStorage(explicit, toolContext) {
46799
47399
  if (explicit) return explicit;
46800
47400
  const factory = exports.StorageRegistry.get("customTools");
46801
47401
  if (factory) {
46802
- return factory(buildStorageContext(toolContext));
47402
+ return factory(buildStorageContext2(toolContext));
46803
47403
  }
46804
47404
  return new FileCustomToolStorage();
46805
47405
  }
@@ -46827,12 +47427,13 @@ function createCustomToolDelete(storage) {
46827
47427
  permission: { scope: "session", riskLevel: "medium" },
46828
47428
  execute: async (args, context) => {
46829
47429
  try {
47430
+ const userId = context?.userId;
46830
47431
  const s = resolveCustomToolStorage(storage, context);
46831
- const exists = await s.exists(args.name);
47432
+ const exists = await s.exists(userId, args.name);
46832
47433
  if (!exists) {
46833
47434
  return { success: false, name: args.name, error: `Custom tool '${args.name}' not found` };
46834
47435
  }
46835
- await s.delete(args.name);
47436
+ await s.delete(userId, args.name);
46836
47437
  return { success: true, name: args.name };
46837
47438
  } catch (error) {
46838
47439
  return { success: false, name: args.name, error: error.message };
@@ -47073,8 +47674,9 @@ function createCustomToolList(storage) {
47073
47674
  },
47074
47675
  permission: { scope: "always", riskLevel: "low" },
47075
47676
  execute: async (args, context) => {
47677
+ const userId = context?.userId;
47076
47678
  const s = resolveCustomToolStorage(storage, context);
47077
- const tools = await s.list({
47679
+ const tools = await s.list(userId, {
47078
47680
  search: args.search,
47079
47681
  tags: args.tags,
47080
47682
  category: args.category,
@@ -47110,8 +47712,9 @@ function createCustomToolLoad(storage) {
47110
47712
  },
47111
47713
  permission: { scope: "always", riskLevel: "low" },
47112
47714
  execute: async (args, context) => {
47715
+ const userId = context?.userId;
47113
47716
  const s = resolveCustomToolStorage(storage, context);
47114
- const tool = await s.load(args.name);
47717
+ const tool = await s.load(userId, args.name);
47115
47718
  if (!tool) {
47116
47719
  return { success: false, error: `Custom tool '${args.name}' not found` };
47117
47720
  }
@@ -47183,9 +47786,10 @@ function createCustomToolSave(storage) {
47183
47786
  permission: { scope: "session", riskLevel: "medium" },
47184
47787
  execute: async (args, context) => {
47185
47788
  try {
47789
+ const userId = context?.userId;
47186
47790
  const s = resolveCustomToolStorage(storage, context);
47187
47791
  const now = (/* @__PURE__ */ new Date()).toISOString();
47188
- const existing = await s.load(args.name);
47792
+ const existing = await s.load(userId, args.name);
47189
47793
  const definition = {
47190
47794
  version: CUSTOM_TOOL_DEFINITION_VERSION,
47191
47795
  name: args.name,
@@ -47204,17 +47808,17 @@ function createCustomToolSave(storage) {
47204
47808
  requiresConnector: (args.connectorNames?.length ?? 0) > 0
47205
47809
  }
47206
47810
  };
47207
- await s.save(definition);
47811
+ await s.save(userId, definition);
47208
47812
  return {
47209
47813
  success: true,
47210
47814
  name: args.name,
47211
- storagePath: s.getPath()
47815
+ storagePath: s.getPath(userId)
47212
47816
  };
47213
47817
  } catch (error) {
47214
47818
  return {
47215
47819
  success: false,
47216
47820
  name: args.name,
47217
- storagePath: resolveCustomToolStorage(storage, context).getPath(),
47821
+ storagePath: resolveCustomToolStorage(storage, context).getPath(context?.userId),
47218
47822
  error: error.message
47219
47823
  };
47220
47824
  }
@@ -48002,6 +48606,7 @@ exports.FileMediaOutputHandler = FileMediaStorage;
48002
48606
  exports.FileMediaStorage = FileMediaStorage;
48003
48607
  exports.FilePersistentInstructionsStorage = FilePersistentInstructionsStorage;
48004
48608
  exports.FileStorage = FileStorage;
48609
+ exports.FileUserInfoStorage = FileUserInfoStorage;
48005
48610
  exports.FormatDetector = FormatDetector;
48006
48611
  exports.HookManager = HookManager;
48007
48612
  exports.IMAGE_MODELS = IMAGE_MODELS;
@@ -48077,6 +48682,7 @@ exports.ToolPermissionManager = ToolPermissionManager;
48077
48682
  exports.ToolRegistry = ToolRegistry;
48078
48683
  exports.ToolTimeoutError = ToolTimeoutError;
48079
48684
  exports.TruncateCompactor = TruncateCompactor;
48685
+ exports.UserInfoPluginNextGen = UserInfoPluginNextGen;
48080
48686
  exports.VENDORS = VENDORS;
48081
48687
  exports.VENDOR_ICON_MAP = VENDOR_ICON_MAP;
48082
48688
  exports.VIDEO_MODELS = VIDEO_MODELS;