assistme 0.8.5 → 0.8.6

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.
@@ -2876,6 +2876,8 @@ var SkillManager = class {
2876
2876
  skills = /* @__PURE__ */ new Map();
2877
2877
  idfCache = /* @__PURE__ */ new Map();
2878
2878
  userId = null;
2879
+ /** Tracks the in-flight loadFromDb() promise so callers can await it. */
2880
+ loadPromise = null;
2879
2881
  /** Bounded cache for findRelevant() — keyed by normalized prompt, invalidated on skill changes. */
2880
2882
  relevanceCache = new LRUCache(MAX_RELEVANCE_CACHE_ENTRIES);
2881
2883
  /** Bounded, TTL-aware cache for marketplace discover results. */
@@ -2885,6 +2887,22 @@ var SkillManager = class {
2885
2887
  }
2886
2888
  async loadFromDb() {
2887
2889
  if (!this.userId) return;
2890
+ if (this.loadPromise) return this.loadPromise;
2891
+ this.loadPromise = this._doLoadFromDb();
2892
+ try {
2893
+ await this.loadPromise;
2894
+ } finally {
2895
+ this.loadPromise = null;
2896
+ }
2897
+ }
2898
+ /**
2899
+ * Wait for any in-flight loadFromDb() to finish.
2900
+ * Safe to call multiple times — resolves immediately if no load is pending.
2901
+ */
2902
+ async ensureLoaded() {
2903
+ if (this.loadPromise) await this.loadPromise;
2904
+ }
2905
+ async _doLoadFromDb() {
2888
2906
  try {
2889
2907
  const data = await callMcpHandler("skill.load");
2890
2908
  this.skills.clear();
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setSessionBusy,
28
28
  toggleScheduledTask,
29
29
  updateHeartbeat
30
- } from "./chunk-4E5QAYTQ.js";
30
+ } from "./chunk-ZBZWNZVA.js";
31
31
  import {
32
32
  HEARTBEAT_INTERVAL_MS,
33
33
  HEARTBEAT_LOG_MAX_ENTRIES,
@@ -19,7 +19,7 @@ import {
19
19
  pollActionResponse,
20
20
  resetEventSequence,
21
21
  setActionRequest
22
- } from "../chunk-4E5QAYTQ.js";
22
+ } from "../chunk-ZBZWNZVA.js";
23
23
  import {
24
24
  EDSGER_PRODUCT_SLUG,
25
25
  JobRunner,
@@ -1778,6 +1778,7 @@ function createAgentToolsServer(deps) {
1778
1778
  description: z2.string().optional().describe("Updated description (optional)")
1779
1779
  },
1780
1780
  async (args) => {
1781
+ await skillManager.ensureLoaded();
1781
1782
  const existing = skillManager.get(args.name);
1782
1783
  if (!existing) {
1783
1784
  const available = skillManager.getAll().map((s) => s.name).join(", ");
@@ -1824,6 +1825,7 @@ function createAgentToolsServer(deps) {
1824
1825
  arguments: z2.string().optional().describe("Arguments to pass to the skill (replaces $ARGUMENTS placeholders)")
1825
1826
  },
1826
1827
  async (args) => {
1828
+ await skillManager.ensureLoaded();
1827
1829
  let skill = skillManager.get(args.name);
1828
1830
  if (!skill) {
1829
1831
  const confirmResult = await confirmMarketplaceSkill(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistme",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "AssistMe CLI Agent - AI-powered agentic assistant for code, browser, and automation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -63,6 +63,9 @@ export class SkillManager {
63
63
  private idfCache: Map<string, number> = new Map();
64
64
  private userId: string | null = null;
65
65
 
66
+ /** Tracks the in-flight loadFromDb() promise so callers can await it. */
67
+ private loadPromise: Promise<void> | null = null;
68
+
66
69
  /** Bounded cache for findRelevant() — keyed by normalized prompt, invalidated on skill changes. */
67
70
  private relevanceCache = new LRUCache<
68
71
  string,
@@ -79,6 +82,26 @@ export class SkillManager {
79
82
  async loadFromDb(): Promise<void> {
80
83
  if (!this.userId) return;
81
84
 
85
+ // Deduplicate concurrent loads: reuse existing in-flight promise
86
+ if (this.loadPromise) return this.loadPromise;
87
+
88
+ this.loadPromise = this._doLoadFromDb();
89
+ try {
90
+ await this.loadPromise;
91
+ } finally {
92
+ this.loadPromise = null;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Wait for any in-flight loadFromDb() to finish.
98
+ * Safe to call multiple times — resolves immediately if no load is pending.
99
+ */
100
+ async ensureLoaded(): Promise<void> {
101
+ if (this.loadPromise) await this.loadPromise;
102
+ }
103
+
104
+ private async _doLoadFromDb(): Promise<void> {
82
105
  try {
83
106
  const data = await callMcpHandler<unknown[]>("skill.load");
84
107
 
@@ -173,6 +173,9 @@ export function createAgentToolsServer(deps: AgentToolsDeps): McpSdkServerConfig
173
173
  description: z.string().optional().describe("Updated description (optional)"),
174
174
  },
175
175
  async (args) => {
176
+ // Ensure DB skills are loaded (avoids race with async loadFromDb)
177
+ await skillManager.ensureLoaded();
178
+
176
179
  const existing = skillManager.get(args.name);
177
180
  if (!existing) {
178
181
  const available = skillManager
@@ -228,6 +231,9 @@ export function createAgentToolsServer(deps: AgentToolsDeps): McpSdkServerConfig
228
231
  .describe("Arguments to pass to the skill (replaces $ARGUMENTS placeholders)"),
229
232
  },
230
233
  async (args) => {
234
+ // Ensure DB skills are loaded (avoids race with async loadFromDb)
235
+ await skillManager.ensureLoaded();
236
+
231
237
  let skill = skillManager.get(args.name);
232
238
 
233
239
  // If not in user's collection, try marketplace — requires user confirmation