assistme 0.8.6 → 0.8.7
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.
|
@@ -2878,6 +2878,8 @@ var SkillManager = class {
|
|
|
2878
2878
|
userId = null;
|
|
2879
2879
|
/** Tracks the in-flight loadFromDb() promise so callers can await it. */
|
|
2880
2880
|
loadPromise = null;
|
|
2881
|
+
/** True once loadFromDb() completes without error (even with 0 skills). */
|
|
2882
|
+
loaded = false;
|
|
2881
2883
|
/** Bounded cache for findRelevant() — keyed by normalized prompt, invalidated on skill changes. */
|
|
2882
2884
|
relevanceCache = new LRUCache(MAX_RELEVANCE_CACHE_ENTRIES);
|
|
2883
2885
|
/** Bounded, TTL-aware cache for marketplace discover results. */
|
|
@@ -2896,11 +2898,31 @@ var SkillManager = class {
|
|
|
2896
2898
|
}
|
|
2897
2899
|
}
|
|
2898
2900
|
/**
|
|
2899
|
-
*
|
|
2900
|
-
*
|
|
2901
|
+
* Guarantee that loadFromDb() has completed at least once.
|
|
2902
|
+
* Awaits any in-flight load; retries once if the initial load failed.
|
|
2903
|
+
* Safe and cheap to call repeatedly — no-ops after the first success.
|
|
2901
2904
|
*/
|
|
2902
2905
|
async ensureLoaded() {
|
|
2903
2906
|
if (this.loadPromise) await this.loadPromise;
|
|
2907
|
+
if (!this.loaded && this.userId) {
|
|
2908
|
+
await this.loadFromDb();
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
/**
|
|
2912
|
+
* Get a skill by name, with a DB search fallback.
|
|
2913
|
+
* Handles: race conditions, failed initial loads, and skills added externally
|
|
2914
|
+
* after the initial load (e.g. created via UI while agent is running).
|
|
2915
|
+
*/
|
|
2916
|
+
async getWithDbFallback(name) {
|
|
2917
|
+
await this.ensureLoaded();
|
|
2918
|
+
const skill = this.skills.get(name);
|
|
2919
|
+
if (skill) return skill;
|
|
2920
|
+
const dbResults = await searchSkillsInDb(name, 5);
|
|
2921
|
+
const match = dbResults?.find((r) => r.name === name);
|
|
2922
|
+
if (!match) return void 0;
|
|
2923
|
+
this.loaded = false;
|
|
2924
|
+
await this.loadFromDb();
|
|
2925
|
+
return this.skills.get(name);
|
|
2904
2926
|
}
|
|
2905
2927
|
async _doLoadFromDb() {
|
|
2906
2928
|
try {
|
|
@@ -2912,6 +2934,7 @@ var SkillManager = class {
|
|
|
2912
2934
|
this.skills.set(row.name, this.rowToSkill(row));
|
|
2913
2935
|
}
|
|
2914
2936
|
this.rebuildIdfCache();
|
|
2937
|
+
this.loaded = true;
|
|
2915
2938
|
if (this.skills.size > 0) {
|
|
2916
2939
|
log.info(`Loaded ${this.skills.size} skill(s) from DB`);
|
|
2917
2940
|
}
|
package/dist/index.js
CHANGED
package/dist/workers/entry.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
pollActionResponse,
|
|
20
20
|
resetEventSequence,
|
|
21
21
|
setActionRequest
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-QBXD76HA.js";
|
|
23
23
|
import {
|
|
24
24
|
EDSGER_PRODUCT_SLUG,
|
|
25
25
|
JobRunner,
|
|
@@ -1778,8 +1778,7 @@ function createAgentToolsServer(deps) {
|
|
|
1778
1778
|
description: z2.string().optional().describe("Updated description (optional)")
|
|
1779
1779
|
},
|
|
1780
1780
|
async (args) => {
|
|
1781
|
-
await skillManager.
|
|
1782
|
-
const existing = skillManager.get(args.name);
|
|
1781
|
+
const existing = await skillManager.getWithDbFallback(args.name);
|
|
1783
1782
|
if (!existing) {
|
|
1784
1783
|
const available = skillManager.getAll().map((s) => s.name).join(", ");
|
|
1785
1784
|
return {
|
|
@@ -1825,8 +1824,7 @@ function createAgentToolsServer(deps) {
|
|
|
1825
1824
|
arguments: z2.string().optional().describe("Arguments to pass to the skill (replaces $ARGUMENTS placeholders)")
|
|
1826
1825
|
},
|
|
1827
1826
|
async (args) => {
|
|
1828
|
-
await skillManager.
|
|
1829
|
-
let skill = skillManager.get(args.name);
|
|
1827
|
+
let skill = await skillManager.getWithDbFallback(args.name);
|
|
1830
1828
|
if (!skill) {
|
|
1831
1829
|
const confirmResult = await confirmMarketplaceSkill(
|
|
1832
1830
|
skillManager,
|
|
@@ -2140,7 +2138,7 @@ Use \`ask_user\` to request these from the user, or create them yourself (e.g. r
|
|
|
2140
2138
|
author_name: z2.string().optional().describe("Your display name as the author")
|
|
2141
2139
|
},
|
|
2142
2140
|
async (args) => {
|
|
2143
|
-
const skill = skillManager.
|
|
2141
|
+
const skill = await skillManager.getWithDbFallback(args.name);
|
|
2144
2142
|
if (!skill) {
|
|
2145
2143
|
return {
|
|
2146
2144
|
content: [
|
|
@@ -3323,6 +3321,7 @@ var TaskProcessor = class {
|
|
|
3323
3321
|
let tokenUsage;
|
|
3324
3322
|
try {
|
|
3325
3323
|
await emitEvent(task.id, "status_change", { status: "running" });
|
|
3324
|
+
await this.skillManager.ensureLoaded();
|
|
3326
3325
|
const systemPrompt = await buildSystemPrompt(task, {
|
|
3327
3326
|
memoryManager: this.memoryManager,
|
|
3328
3327
|
skillManager: this.skillManager,
|
package/package.json
CHANGED
package/src/agent/processor.ts
CHANGED
|
@@ -181,6 +181,9 @@ export class TaskProcessor {
|
|
|
181
181
|
try {
|
|
182
182
|
await emitEvent(task.id, "status_change", { status: "running" });
|
|
183
183
|
|
|
184
|
+
// Guarantee skills are loaded before building prompt or running tools
|
|
185
|
+
await this.skillManager.ensureLoaded();
|
|
186
|
+
|
|
184
187
|
// Build system prompt with memories + skills + history
|
|
185
188
|
const systemPrompt = await buildSystemPrompt(task, {
|
|
186
189
|
memoryManager: this.memoryManager,
|
package/src/agent/skills.ts
CHANGED
|
@@ -65,6 +65,8 @@ export class SkillManager {
|
|
|
65
65
|
|
|
66
66
|
/** Tracks the in-flight loadFromDb() promise so callers can await it. */
|
|
67
67
|
private loadPromise: Promise<void> | null = null;
|
|
68
|
+
/** True once loadFromDb() completes without error (even with 0 skills). */
|
|
69
|
+
private loaded = false;
|
|
68
70
|
|
|
69
71
|
/** Bounded cache for findRelevant() — keyed by normalized prompt, invalidated on skill changes. */
|
|
70
72
|
private relevanceCache = new LRUCache<
|
|
@@ -94,11 +96,37 @@ export class SkillManager {
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
+
* Guarantee that loadFromDb() has completed at least once.
|
|
100
|
+
* Awaits any in-flight load; retries once if the initial load failed.
|
|
101
|
+
* Safe and cheap to call repeatedly — no-ops after the first success.
|
|
99
102
|
*/
|
|
100
103
|
async ensureLoaded(): Promise<void> {
|
|
101
104
|
if (this.loadPromise) await this.loadPromise;
|
|
105
|
+
if (!this.loaded && this.userId) {
|
|
106
|
+
await this.loadFromDb();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get a skill by name, with a DB search fallback.
|
|
112
|
+
* Handles: race conditions, failed initial loads, and skills added externally
|
|
113
|
+
* after the initial load (e.g. created via UI while agent is running).
|
|
114
|
+
*/
|
|
115
|
+
async getWithDbFallback(name: string): Promise<Skill | undefined> {
|
|
116
|
+
await this.ensureLoaded();
|
|
117
|
+
|
|
118
|
+
const skill = this.skills.get(name);
|
|
119
|
+
if (skill) return skill;
|
|
120
|
+
|
|
121
|
+
// In-memory miss: check if the skill exists in DB via search
|
|
122
|
+
const dbResults = await searchSkillsInDb(name, 5);
|
|
123
|
+
const match = dbResults?.find((r) => r.name === name);
|
|
124
|
+
if (!match) return undefined;
|
|
125
|
+
|
|
126
|
+
// Found in DB — reload all skills into memory and return
|
|
127
|
+
this.loaded = false; // force reload
|
|
128
|
+
await this.loadFromDb();
|
|
129
|
+
return this.skills.get(name);
|
|
102
130
|
}
|
|
103
131
|
|
|
104
132
|
private async _doLoadFromDb(): Promise<void> {
|
|
@@ -113,6 +141,7 @@ export class SkillManager {
|
|
|
113
141
|
}
|
|
114
142
|
|
|
115
143
|
this.rebuildIdfCache();
|
|
144
|
+
this.loaded = true;
|
|
116
145
|
|
|
117
146
|
if (this.skills.size > 0) {
|
|
118
147
|
log.info(`Loaded ${this.skills.size} skill(s) from DB`);
|
|
@@ -173,10 +173,8 @@ export function createAgentToolsServer(deps: AgentToolsDeps): McpSdkServerConfig
|
|
|
173
173
|
description: z.string().optional().describe("Updated description (optional)"),
|
|
174
174
|
},
|
|
175
175
|
async (args) => {
|
|
176
|
-
//
|
|
177
|
-
await skillManager.
|
|
178
|
-
|
|
179
|
-
const existing = skillManager.get(args.name);
|
|
176
|
+
// Use DB fallback to handle race condition with async loadFromDb
|
|
177
|
+
const existing = await skillManager.getWithDbFallback(args.name);
|
|
180
178
|
if (!existing) {
|
|
181
179
|
const available = skillManager
|
|
182
180
|
.getAll()
|
|
@@ -231,10 +229,8 @@ export function createAgentToolsServer(deps: AgentToolsDeps): McpSdkServerConfig
|
|
|
231
229
|
.describe("Arguments to pass to the skill (replaces $ARGUMENTS placeholders)"),
|
|
232
230
|
},
|
|
233
231
|
async (args) => {
|
|
234
|
-
//
|
|
235
|
-
await skillManager.
|
|
236
|
-
|
|
237
|
-
let skill = skillManager.get(args.name);
|
|
232
|
+
// Use DB fallback to handle race condition with async loadFromDb
|
|
233
|
+
let skill = await skillManager.getWithDbFallback(args.name);
|
|
238
234
|
|
|
239
235
|
// If not in user's collection, try marketplace — requires user confirmation
|
|
240
236
|
if (!skill) {
|
|
@@ -547,7 +543,7 @@ export function createAgentToolsServer(deps: AgentToolsDeps): McpSdkServerConfig
|
|
|
547
543
|
author_name: z.string().optional().describe("Your display name as the author"),
|
|
548
544
|
},
|
|
549
545
|
async (args) => {
|
|
550
|
-
const skill = skillManager.
|
|
546
|
+
const skill = await skillManager.getWithDbFallback(args.name);
|
|
551
547
|
if (!skill) {
|
|
552
548
|
return {
|
|
553
549
|
content: [
|