assistme 0.8.4 → 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.
@@ -340,7 +340,6 @@ var MAX_CONTENT_SEARCH_RESULTS = 30;
340
340
  var MEMORY_DEDUP_SIMILARITY_THRESHOLD = 0.75;
341
341
  var MEMORY_COMPRESSION_THRESHOLD = 50;
342
342
  var MEMORY_COMPRESSION_TARGET = 30;
343
- var MAX_BUDGET_USD = 2;
344
343
  var SELF_ANALYSIS_MAX_SESSION_LOGS = 200;
345
344
  var SELF_ANALYSIS_MAX_MESSAGE_EVENTS = 300;
346
345
  var SELF_ANALYSIS_MAX_CONVERSATION_MESSAGES = 10;
@@ -589,7 +588,6 @@ export {
589
588
  MEMORY_DEDUP_SIMILARITY_THRESHOLD,
590
589
  MEMORY_COMPRESSION_THRESHOLD,
591
590
  MEMORY_COMPRESSION_TARGET,
592
- MAX_BUDGET_USD,
593
591
  SELF_ANALYSIS_MAX_SESSION_LOGS,
594
592
  SELF_ANALYSIS_MAX_MESSAGE_EVENTS,
595
593
  SELF_ANALYSIS_MAX_CONVERSATION_MESSAGES,
@@ -17,7 +17,7 @@ import {
17
17
  readAuthStore,
18
18
  safeParse,
19
19
  writeAuthStore
20
- } from "./chunk-3UNXN3BX.js";
20
+ } from "./chunk-QGH5MFJA.js";
21
21
  import {
22
22
  AppError,
23
23
  errorMessage,
@@ -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-R7A3MKYO.js";
30
+ } from "./chunk-ZBZWNZVA.js";
31
31
  import {
32
32
  HEARTBEAT_INTERVAL_MS,
33
33
  HEARTBEAT_LOG_MAX_ENTRIES,
@@ -39,7 +39,7 @@ import {
39
39
  setLogConversationId,
40
40
  setLogHook,
41
41
  setLogLevel
42
- } from "./chunk-3UNXN3BX.js";
42
+ } from "./chunk-QGH5MFJA.js";
43
43
  import {
44
44
  clearConfig,
45
45
  errorMessage,
@@ -2159,7 +2159,7 @@ function registerJobCommands(program2) {
2159
2159
  jobCmd.command("list").description("List your defined jobs").action(async () => {
2160
2160
  try {
2161
2161
  await getCurrentUserId();
2162
- const { JobRunner: JobRunner2 } = await import("./job-runner-P4DIXXCV.js");
2162
+ const { JobRunner: JobRunner2 } = await import("./job-runner-IBVUDW6A.js");
2163
2163
  const runner = new JobRunner2();
2164
2164
  const jobs = await runner.listJobs();
2165
2165
  if (jobs.length === 0) {
@@ -2183,7 +2183,7 @@ function registerJobCommands(program2) {
2183
2183
  jobCmd.command("status [name]").description("Show run history for a job (or all jobs)").option("-l, --limit <number>", "Max runs to show (default: 5)").action(async (name, opts) => {
2184
2184
  try {
2185
2185
  await getCurrentUserId();
2186
- const { JobRunner: JobRunner2 } = await import("./job-runner-P4DIXXCV.js");
2186
+ const { JobRunner: JobRunner2 } = await import("./job-runner-IBVUDW6A.js");
2187
2187
  const runner = new JobRunner2();
2188
2188
  const runs = await runner.getRunHistory(name, parseInt(opts.limit || "5"));
2189
2189
  if (runs.length === 0) {
@@ -2222,7 +2222,7 @@ Job Run History${name ? ` \u2014 ${name}` : ""}:`));
2222
2222
  process.exit(1);
2223
2223
  }
2224
2224
  await getCurrentUserId();
2225
- const { JobRunner: JobRunner2 } = await import("./job-runner-P4DIXXCV.js");
2225
+ const { JobRunner: JobRunner2 } = await import("./job-runner-IBVUDW6A.js");
2226
2226
  const runner = new JobRunner2();
2227
2227
  const job = await runner.loadJob(name);
2228
2228
  if (!job) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  JobRunner
3
- } from "./chunk-3UNXN3BX.js";
3
+ } from "./chunk-QGH5MFJA.js";
4
4
  import "./chunk-HY3FFXSQ.js";
5
5
  export {
6
6
  JobRunner
@@ -19,11 +19,10 @@ import {
19
19
  pollActionResponse,
20
20
  resetEventSequence,
21
21
  setActionRequest
22
- } from "../chunk-R7A3MKYO.js";
22
+ } from "../chunk-ZBZWNZVA.js";
23
23
  import {
24
24
  EDSGER_PRODUCT_SLUG,
25
25
  JobRunner,
26
- MAX_BUDGET_USD,
27
26
  MAX_COMPLETE_TASK_RETRIES,
28
27
  MAX_CONTENT_SEARCH_FILES,
29
28
  MAX_CONTENT_SEARCH_RESULTS,
@@ -47,7 +46,7 @@ import {
47
46
  safeParse,
48
47
  setCorrelationId,
49
48
  setLogTransport
50
- } from "../chunk-3UNXN3BX.js";
49
+ } from "../chunk-QGH5MFJA.js";
51
50
  import {
52
51
  AppError,
53
52
  assertWithinAssistMeRoot,
@@ -1779,6 +1778,7 @@ function createAgentToolsServer(deps) {
1779
1778
  description: z2.string().optional().describe("Updated description (optional)")
1780
1779
  },
1781
1780
  async (args) => {
1781
+ await skillManager.ensureLoaded();
1782
1782
  const existing = skillManager.get(args.name);
1783
1783
  if (!existing) {
1784
1784
  const available = skillManager.getAll().map((s) => s.name).join(", ");
@@ -1825,6 +1825,7 @@ function createAgentToolsServer(deps) {
1825
1825
  arguments: z2.string().optional().describe("Arguments to pass to the skill (replaces $ARGUMENTS placeholders)")
1826
1826
  },
1827
1827
  async (args) => {
1828
+ await skillManager.ensureLoaded();
1828
1829
  let skill = skillManager.get(args.name);
1829
1830
  if (!skill) {
1830
1831
  const confirmResult = await confirmMarketplaceSkill(
@@ -3328,7 +3329,7 @@ var TaskProcessor = class {
3328
3329
  historyCache: this.historyCache
3329
3330
  });
3330
3331
  const abortController = new AbortController();
3331
- const taskTimeout = new TaskTimeout(abortController, taskTimeoutMs);
3332
+ const taskTimeout = taskTimeoutMs > 0 ? new TaskTimeout(abortController, taskTimeoutMs) : null;
3332
3333
  const browserServer = createBrowserMcpServer();
3333
3334
  const agentToolsServer = createAgentToolsServer({
3334
3335
  memoryManager: this.memoryManager,
@@ -3336,8 +3337,8 @@ var TaskProcessor = class {
3336
3337
  taskId: task.id,
3337
3338
  sessionId: this.sessionId || void 0,
3338
3339
  heartbeatEngine: this.heartbeatEngine || void 0,
3339
- onUserWaitStart: () => taskTimeout.pause(),
3340
- onUserWaitEnd: () => taskTimeout.resume()
3340
+ onUserWaitStart: () => taskTimeout?.pause(),
3341
+ onUserWaitEnd: () => taskTimeout?.resume()
3341
3342
  });
3342
3343
  const eventHooks = createEventHooks(task.id, toolCallRecords, toolFailures);
3343
3344
  const options = {
@@ -3357,10 +3358,9 @@ var TaskProcessor = class {
3357
3358
  },
3358
3359
  hooks: eventHooks,
3359
3360
  persistSession: true,
3360
- abortController,
3361
+ ...taskTimeout ? { abortController } : {},
3361
3362
  thinking: { type: "adaptive" },
3362
- effort: "high",
3363
- maxBudgetUsd: MAX_BUDGET_USD
3363
+ effort: "high"
3364
3364
  };
3365
3365
  let result;
3366
3366
  try {
@@ -3378,7 +3378,7 @@ var TaskProcessor = class {
3378
3378
  }
3379
3379
  });
3380
3380
  } finally {
3381
- taskTimeout.clear();
3381
+ taskTimeout?.clear();
3382
3382
  }
3383
3383
  const { response: finalResponse, sessionId: agentSessionId, costUsd, numTurns } = result;
3384
3384
  tokenUsage = result.tokenUsage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistme",
3
- "version": "0.8.4",
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",
@@ -39,7 +39,6 @@ import {
39
39
  MAX_RESPONSE_CONTENT_LENGTH,
40
40
  MAX_HISTORY_ENTRIES,
41
41
  MAX_COMPLETE_TASK_RETRIES,
42
- MAX_BUDGET_USD,
43
42
  } from "../utils/constants.js";
44
43
  import { errorMessage } from "../utils/errors.js";
45
44
  import type { HeartbeatEngine } from "./proactive-monitor.js";
@@ -190,7 +189,8 @@ export class TaskProcessor {
190
189
  });
191
190
 
192
191
  const abortController = new AbortController();
193
- const taskTimeout = new TaskTimeout(abortController, taskTimeoutMs);
192
+ const taskTimeout =
193
+ taskTimeoutMs > 0 ? new TaskTimeout(abortController, taskTimeoutMs) : null;
194
194
 
195
195
  // Create MCP servers for custom tools
196
196
  const browserServer = createBrowserMcpServer();
@@ -200,8 +200,8 @@ export class TaskProcessor {
200
200
  taskId: task.id,
201
201
  sessionId: this.sessionId || undefined,
202
202
  heartbeatEngine: this.heartbeatEngine || undefined,
203
- onUserWaitStart: () => taskTimeout.pause(),
204
- onUserWaitEnd: () => taskTimeout.resume(),
203
+ onUserWaitStart: () => taskTimeout?.pause(),
204
+ onUserWaitEnd: () => taskTimeout?.resume(),
205
205
  });
206
206
 
207
207
  const eventHooks = createEventHooks(task.id, toolCallRecords, toolFailures);
@@ -223,10 +223,9 @@ export class TaskProcessor {
223
223
  },
224
224
  hooks: eventHooks,
225
225
  persistSession: true,
226
- abortController,
226
+ ...(taskTimeout ? { abortController } : {}),
227
227
  thinking: { type: "adaptive" },
228
228
  effort: "high",
229
- maxBudgetUsd: MAX_BUDGET_USD,
230
229
  };
231
230
 
232
231
  // Execute via SDK with real-time event streaming
@@ -246,7 +245,7 @@ export class TaskProcessor {
246
245
  },
247
246
  });
248
247
  } finally {
249
- taskTimeout.clear();
248
+ taskTimeout?.clear();
250
249
  }
251
250
 
252
251
  const { response: finalResponse, sessionId: agentSessionId, costUsd, numTurns } = result;
@@ -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
@@ -31,8 +31,8 @@ export const SKILL_DESCRIPTION_BUDGET_CHARS = 16_000;
31
31
 
32
32
  // ── Timeouts ───────────────────────────────────────────────────────
33
33
 
34
- /** Default task timeout in minutes */
35
- export const DEFAULT_TASK_TIMEOUT_MINUTES = 10;
34
+ /** Default task timeout in minutes (0 = no timeout) */
35
+ export const DEFAULT_TASK_TIMEOUT_MINUTES = 0;
36
36
 
37
37
  /** Shell command execution timeout in ms */
38
38
  export const SHELL_TIMEOUT_MS = 30_000;