assistme 0.8.1 → 0.8.3

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.
Files changed (89) hide show
  1. package/dist/{chunk-QHMIXIWO.js → chunk-3UNXN3BX.js} +129 -44
  2. package/dist/chunk-HY3FFXSQ.js +113 -0
  3. package/dist/{chunk-4RHN77BN.js → chunk-UHGTMSLZ.js} +640 -327
  4. package/dist/config-2HH7PO34.js +20 -0
  5. package/dist/index.js +643 -670
  6. package/dist/job-runner-P4DIXXCV.js +7 -0
  7. package/dist/workers/entry.js +548 -649
  8. package/package.json +1 -1
  9. package/src/NAMING.md +34 -0
  10. package/src/agent/heartbeat-checks.ts +158 -0
  11. package/src/agent/heartbeat-compiler.ts +122 -0
  12. package/src/agent/heartbeat-types.ts +62 -0
  13. package/src/agent/job-analysis-poller.ts +96 -0
  14. package/src/agent/job-runner.ts +31 -0
  15. package/src/agent/proactive-monitor.ts +88 -410
  16. package/src/agent/processor.ts +147 -252
  17. package/src/agent/prompt-builder.ts +83 -0
  18. package/src/agent/scheduler.ts +1 -1
  19. package/src/agent/sdk-stream.ts +105 -0
  20. package/src/agent/self-analyzer.ts +22 -23
  21. package/src/agent/session-heartbeat.ts +34 -0
  22. package/src/agent/skill-db.ts +170 -0
  23. package/src/agent/skill-evaluator.ts +4 -13
  24. package/src/agent/skill-format.ts +96 -0
  25. package/src/agent/skill-marketplace.ts +98 -0
  26. package/src/agent/skill-search.ts +315 -0
  27. package/src/agent/skill-types.ts +68 -0
  28. package/src/agent/skill-utils.ts +66 -0
  29. package/src/agent/skills.ts +265 -566
  30. package/src/agent/system-prompt.ts +11 -8
  31. package/src/agent/task-poller.ts +101 -0
  32. package/src/agent/task-timeout.ts +50 -0
  33. package/src/browser/chrome-launcher.ts +6 -6
  34. package/src/browser/controller.ts +1 -2
  35. package/src/commands/auth.ts +4 -11
  36. package/src/commands/browser.ts +12 -47
  37. package/src/commands/credential.ts +2 -2
  38. package/src/commands/job.ts +3 -3
  39. package/src/commands/monitor.ts +3 -5
  40. package/src/commands/start.ts +3 -3
  41. package/src/credentials/encryption.ts +4 -10
  42. package/src/credentials/local-store.ts +4 -7
  43. package/src/credentials/program-store.ts +8 -10
  44. package/src/db/analysis-data.ts +4 -1
  45. package/src/db/auth-store.ts +15 -13
  46. package/src/db/session-log.ts +13 -5
  47. package/src/mcp/agent-tools-server.ts +126 -102
  48. package/src/mcp/ask-user.ts +102 -0
  49. package/src/mcp/skill-confirmation.ts +109 -0
  50. package/src/orchestrator.ts +100 -249
  51. package/src/tools/filesystem.ts +48 -2
  52. package/src/tools/index.ts +1 -2
  53. package/src/tools/shell.ts +58 -2
  54. package/src/types/edsger-feedback.d.ts +18 -0
  55. package/src/utils/config.ts +79 -1
  56. package/src/utils/logger.ts +100 -10
  57. package/src/utils/lru-cache.ts +57 -0
  58. package/src/utils/schemas.ts +2 -0
  59. package/src/workers/base-handler.ts +18 -1
  60. package/src/workers/conversation.ts +4 -1
  61. package/src/workers/entry.ts +1 -5
  62. package/src/workers/index.ts +2 -0
  63. package/src/workers/log-forwarder.ts +55 -0
  64. package/src/workers/manager.ts +85 -209
  65. package/src/workers/types.ts +21 -5
  66. package/src/workers/worker-lifecycle.ts +113 -0
  67. package/tests/agent/heartbeat-checks.test.ts +160 -0
  68. package/tests/agent/mcp-servers.test.ts +1 -1
  69. package/tests/agent/proactive-monitor.test.ts +42 -26
  70. package/tests/agent/processor.test.ts +2 -1
  71. package/tests/agent/sdk-stream.test.ts +181 -0
  72. package/tests/agent/self-analyzer.test.ts +106 -49
  73. package/tests/agent/session.test.ts +114 -132
  74. package/tests/agent/skill-format.test.ts +93 -0
  75. package/tests/agent/skill-search.test.ts +175 -0
  76. package/tests/agent/skill-utils.test.ts +86 -0
  77. package/tests/agent/skills.test.ts +4 -24
  78. package/tests/db/supabase.test.ts +3 -2
  79. package/tests/mcp/ask-user.test.ts +117 -0
  80. package/tests/mcp/skill-confirmation.integration.test.ts +216 -0
  81. package/tests/mcp/skill-confirmation.test.ts +66 -0
  82. package/tests/tools/filesystem.test.ts +38 -1
  83. package/tests/tools/shell.test.ts +43 -0
  84. package/tests/utils/config.test.ts +2 -2
  85. package/dist/chunk-YYSJHZSO.js +0 -47
  86. package/dist/config-3RWSAUAZ.js +0 -12
  87. package/dist/job-runner-YM2NBIL3.js +0 -7
  88. package/src/agent/session.ts +0 -348
  89. package/src/workers/job-analyzer.ts +0 -415
@@ -1,32 +1,33 @@
1
1
  import {
2
- getConfig
3
- } from "./chunk-YYSJHZSO.js";
2
+ errorMessage,
3
+ getConfig,
4
+ getDataDir
5
+ } from "./chunk-HY3FFXSQ.js";
4
6
 
5
7
  // src/db/auth-store.ts
6
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
8
+ import { existsSync, readFileSync, writeFileSync } from "fs";
7
9
  import { join } from "path";
8
- import { homedir } from "os";
9
- var AUTH_DIR = join(homedir(), ".config", "assistme");
10
- var AUTH_FILE = join(AUTH_DIR, "auth.json");
11
- function ensureAuthDir() {
12
- if (!existsSync(AUTH_DIR)) {
13
- mkdirSync(AUTH_DIR, { recursive: true, mode: 448 });
14
- }
10
+ function getAuthFile() {
11
+ return join(getDataDir(), "auth.json");
15
12
  }
16
13
  function readAuthStore() {
17
14
  try {
18
- if (existsSync(AUTH_FILE)) {
19
- return JSON.parse(readFileSync(AUTH_FILE, "utf-8"));
15
+ const authFile = getAuthFile();
16
+ if (existsSync(authFile)) {
17
+ return JSON.parse(readFileSync(authFile, "utf-8"));
20
18
  }
21
19
  } catch {
22
20
  }
23
21
  return {};
24
22
  }
25
23
  function writeAuthStore(data) {
26
- ensureAuthDir();
27
- writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2), { mode: 384 });
24
+ writeFileSync(getAuthFile(), JSON.stringify(data, null, 2), { mode: 384 });
28
25
  }
29
26
  function getRawToken() {
27
+ const envToken = process.env.ASSISTME_TOKEN;
28
+ if (envToken && envToken.startsWith("am_")) {
29
+ return envToken;
30
+ }
30
31
  const store = readAuthStore();
31
32
  const token = store["mcp_token"];
32
33
  if (!token || !token.startsWith("am_")) {
@@ -59,9 +60,28 @@ async function callMcpHandler(action, params = {}, overrideToken) {
59
60
  // src/utils/logger.ts
60
61
  import chalk from "chalk";
61
62
  import { randomUUID } from "crypto";
63
+ import { readFileSync as readFileSync2 } from "fs";
64
+ import { join as join2, dirname } from "path";
65
+ import { fileURLToPath } from "url";
62
66
  var currentLevel = "info";
63
67
  var currentCorrelationId = null;
68
+ var currentConversationId = null;
64
69
  var logHook = null;
70
+ var logTransport = null;
71
+ var PKG_VERSION = (() => {
72
+ try {
73
+ const __dirname = dirname(fileURLToPath(import.meta.url));
74
+ for (const rel of ["../package.json", "../../package.json"]) {
75
+ try {
76
+ const pkg = JSON.parse(readFileSync2(join2(__dirname, rel), "utf-8"));
77
+ if (pkg.version) return pkg.version;
78
+ } catch {
79
+ }
80
+ }
81
+ } catch {
82
+ }
83
+ return "unknown";
84
+ })();
65
85
  var LEVEL_ORDER = {
66
86
  debug: 0,
67
87
  info: 1,
@@ -74,9 +94,15 @@ function setLogLevel(level) {
74
94
  function setLogHook(hook) {
75
95
  logHook = hook;
76
96
  }
97
+ function setLogTransport(transport) {
98
+ logTransport = transport;
99
+ }
77
100
  function setCorrelationId(id) {
78
101
  currentCorrelationId = id;
79
102
  }
103
+ function setLogConversationId(id) {
104
+ currentConversationId = id;
105
+ }
80
106
  function newCorrelationId() {
81
107
  const id = randomUUID().slice(0, 8);
82
108
  currentCorrelationId = id;
@@ -90,54 +116,87 @@ function timestamp() {
90
116
  }
91
117
  function prefix() {
92
118
  const ts = timestamp();
93
- return currentCorrelationId ? `${ts} ${currentCorrelationId}` : ts;
119
+ const base = `${ts} v${PKG_VERSION}`;
120
+ return currentCorrelationId ? `${base} ${currentCorrelationId}` : base;
94
121
  }
95
122
  var log = {
96
123
  debug(msg, ...args) {
97
124
  if (shouldLog("debug")) {
98
125
  const text = formatArgs(msg, args);
99
- logHook?.("stdout", `[DEBUG] ${text}`);
126
+ if (logTransport) {
127
+ logTransport("debug", text);
128
+ return;
129
+ }
130
+ logHook?.("stdout", `[DEBUG] ${text}`, currentConversationId);
100
131
  console.log(chalk.gray(`[${prefix()}] DEBUG`), msg, ...args);
101
132
  }
102
133
  },
103
134
  info(msg, ...args) {
104
135
  if (shouldLog("info")) {
105
136
  const text = formatArgs(msg, args);
106
- logHook?.("stdout", text);
137
+ if (logTransport) {
138
+ logTransport("info", text);
139
+ return;
140
+ }
141
+ logHook?.("stdout", text, currentConversationId);
107
142
  console.log(chalk.blue(`[${prefix()}]`), msg, ...args);
108
143
  }
109
144
  },
110
145
  success(msg, ...args) {
111
146
  if (shouldLog("info")) {
112
147
  const text = formatArgs(msg, args);
113
- logHook?.("stdout", `\u2713 ${text}`);
148
+ if (logTransport) {
149
+ logTransport("success", text);
150
+ return;
151
+ }
152
+ logHook?.("stdout", `\u2713 ${text}`, currentConversationId);
114
153
  console.log(chalk.green(`[${prefix()}] \u2713`), msg, ...args);
115
154
  }
116
155
  },
117
156
  warn(msg, ...args) {
118
157
  if (shouldLog("warn")) {
119
158
  const text = formatArgs(msg, args);
120
- logHook?.("stderr", `[WARN] ${text}`);
159
+ if (logTransport) {
160
+ logTransport("warn", text);
161
+ return;
162
+ }
163
+ logHook?.("stderr", `[WARN] ${text}`, currentConversationId);
121
164
  console.log(chalk.yellow(`[${prefix()}] WARN`), msg, ...args);
122
165
  }
123
166
  },
124
167
  error(msg, ...args) {
125
168
  if (shouldLog("error")) {
126
169
  const text = formatArgs(msg, args);
127
- logHook?.("stderr", `[ERROR] ${text}`);
170
+ if (logTransport) {
171
+ logTransport("error", text);
172
+ return;
173
+ }
174
+ logHook?.("stderr", `[ERROR] ${text}`, currentConversationId);
128
175
  console.error(chalk.red(`[${prefix()}] ERROR`), msg, ...args);
129
176
  }
130
177
  },
131
178
  agent(msg) {
132
- logHook?.("stdout", `\u25B8 ${msg}`);
179
+ if (logTransport) {
180
+ logTransport("agent", msg);
181
+ return;
182
+ }
183
+ logHook?.("stdout", `\u25B8 ${msg}`, currentConversationId);
133
184
  console.log(chalk.cyan(" \u25B8"), msg);
134
185
  },
135
186
  tool(name, msg) {
136
- logHook?.("stdout", `\u26A1 ${name}: ${msg}`);
187
+ if (logTransport) {
188
+ logTransport("tool", msg, name);
189
+ return;
190
+ }
191
+ logHook?.("stdout", `\u26A1 ${name}: ${msg}`, currentConversationId);
137
192
  console.log(chalk.magenta(` \u26A1 ${name}:`), msg);
138
193
  },
139
194
  result(msg) {
140
- logHook?.("stdout", `\u2190 ${msg}`);
195
+ if (logTransport) {
196
+ logTransport("result", msg);
197
+ return;
198
+ }
199
+ logHook?.("stdout", `\u2190 ${msg}`, currentConversationId);
141
200
  console.log(chalk.green(" \u2190"), msg);
142
201
  }
143
202
  };
@@ -294,25 +353,6 @@ var HEARTBEAT_MAX_BUDGET_USD = 0.25;
294
353
  var HEARTBEAT_LOG_MAX_ENTRIES = 100;
295
354
  var MAX_COMPLETE_TASK_RETRIES = 2;
296
355
 
297
- // src/utils/errors.ts
298
- var AppError = class _AppError extends Error {
299
- constructor(message, code, cause) {
300
- super(message);
301
- this.code = code;
302
- this.cause = cause;
303
- this.name = "AppError";
304
- }
305
- static fromUnknown(err, code = "INTERNAL") {
306
- if (err instanceof _AppError) return err;
307
- const message = err instanceof Error ? err.message : String(err);
308
- return new _AppError(message, code, err);
309
- }
310
- };
311
- function errorMessage(err) {
312
- if (err instanceof Error) return err.message;
313
- return String(err);
314
- }
315
-
316
356
  // src/agent/job-runner.ts
317
357
  var JobRunner = class {
318
358
  /**
@@ -417,6 +457,51 @@ var JobRunner = class {
417
457
  return [];
418
458
  }
419
459
  }
460
+ /**
461
+ * Build a prompt for analyzing a job's skill requirements.
462
+ * Used by the orchestrator to dispatch analysis tasks for newly created jobs.
463
+ */
464
+ buildJobAnalysisPrompt(job) {
465
+ let prompt = `Analyze this job definition and determine what skills are needed to execute it effectively.
466
+
467
+ `;
468
+ prompt += `## Job Definition
469
+ `;
470
+ prompt += `**Name:** ${job.jobName}
471
+ `;
472
+ prompt += `**Description:** ${job.jobDescription}
473
+
474
+ `;
475
+ if (job.skills.length > 0) {
476
+ prompt += `**Current Skills:**
477
+ `;
478
+ for (const skill of job.skills) {
479
+ const emoji = skill.skillEmoji ? `${skill.skillEmoji} ` : "";
480
+ prompt += `- ${emoji}${skill.skillName}: ${skill.skillDescription}
481
+ `;
482
+ }
483
+ prompt += `
484
+ `;
485
+ }
486
+ prompt += `## Instructions
487
+ `;
488
+ prompt += `For each capability the job needs:
489
+ `;
490
+ prompt += `1. Check if an existing skill covers it (use \`skill_search\` to check)
491
+ `;
492
+ prompt += `2. If no existing skill covers it, create a new one using \`skill_create\`
493
+ `;
494
+ prompt += `3. If an existing skill needs improvement, update it using \`skill_improve\`
495
+ `;
496
+ prompt += `4. Link all relevant skills to the job using \`skill_link_job\`
497
+
498
+ `;
499
+ prompt += `Be practical \u2014 only create skills that would genuinely help automate this job.
500
+ `;
501
+ prompt += `When done, summarize what skills were created, updated, or already existed.
502
+ `;
503
+ return prompt;
504
+ }
420
505
  /**
421
506
  * Build the agentic prompt for the agent to execute a job.
422
507
  *
@@ -480,7 +565,9 @@ export {
480
565
  callMcpHandler,
481
566
  setLogLevel,
482
567
  setLogHook,
568
+ setLogTransport,
483
569
  setCorrelationId,
570
+ setLogConversationId,
484
571
  newCorrelationId,
485
572
  log,
486
573
  MAX_RESPONSE_CONTENT_LENGTH,
@@ -514,8 +601,6 @@ export {
514
601
  HEARTBEAT_MAX_BUDGET_USD,
515
602
  HEARTBEAT_LOG_MAX_ENTRIES,
516
603
  MAX_COMPLETE_TASK_RETRIES,
517
- AppError,
518
- errorMessage,
519
604
  safeParse,
520
605
  SkillRowSchema,
521
606
  SkillCreateResultSchema,
@@ -0,0 +1,113 @@
1
+ // src/utils/config.ts
2
+ import Conf from "conf";
3
+ import { resolve, basename, join, relative, sep } from "path";
4
+ import { existsSync, mkdirSync } from "fs";
5
+
6
+ // src/utils/errors.ts
7
+ var AppError = class _AppError extends Error {
8
+ constructor(message, code, cause) {
9
+ super(message);
10
+ this.code = code;
11
+ this.cause = cause;
12
+ this.name = "AppError";
13
+ }
14
+ static fromUnknown(err, code = "INTERNAL") {
15
+ if (err instanceof _AppError) return err;
16
+ const message = err instanceof Error ? err.message : String(err);
17
+ return new _AppError(message, code, err);
18
+ }
19
+ };
20
+ function errorMessage(err) {
21
+ if (err instanceof Error) return err.message;
22
+ return String(err);
23
+ }
24
+
25
+ // src/utils/config.ts
26
+ var SUPABASE_URL_DEFAULT = process.env.ASSISTME_SUPABASE_URL || "https://msgplwbgohpokajtibew.supabase.co";
27
+ var SUPABASE_ANON_KEY_DEFAULT = process.env.ASSISTME_SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im1zZ3Bsd2Jnb2hwb2thanRpYmV3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjE3MTMzNTEsImV4cCI6MjA3NzI4OTM1MX0.YqiluL_mIBWKv5dteIcPAPQ_jRp9rzZlvAXvkQttDjs";
28
+ var CONFIG_DEFAULTS = {
29
+ supabaseUrl: SUPABASE_URL_DEFAULT,
30
+ supabaseAnonKey: SUPABASE_ANON_KEY_DEFAULT,
31
+ sessionName: "Default",
32
+ model: "claude-sonnet-4-20250514",
33
+ taskTimeoutMinutes: 10
34
+ };
35
+ var config = new Conf({
36
+ projectName: "assistme",
37
+ defaults: CONFIG_DEFAULTS
38
+ });
39
+ function getConfig() {
40
+ const supabaseUrl = process.env.SUPABASE_URL || config.get("supabaseUrl") || SUPABASE_URL_DEFAULT;
41
+ const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || config.get("supabaseAnonKey") || SUPABASE_ANON_KEY_DEFAULT;
42
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY || config.get("anthropicApiKey") || "";
43
+ const workspacePath = config.get("workspacePath") || process.cwd();
44
+ return {
45
+ supabaseUrl,
46
+ supabaseAnonKey,
47
+ anthropicApiKey,
48
+ workspacePath: resolve(workspacePath),
49
+ sessionName: config.get("sessionName") || "Default",
50
+ model: config.get("model") || "claude-sonnet-4-20250514",
51
+ taskTimeoutMinutes: config.get("taskTimeoutMinutes") || 10
52
+ };
53
+ }
54
+ function setConfig(key, value) {
55
+ config.set(key, value);
56
+ }
57
+ function clearConfig() {
58
+ config.clear();
59
+ }
60
+ function getConfigPath() {
61
+ return config.path;
62
+ }
63
+ var DATA_DIR_NAME = ".assistme-data";
64
+ var _rootCache = null;
65
+ var _dataDirCache = null;
66
+ function getAssistMeRoot() {
67
+ if (_rootCache) return _rootCache;
68
+ const { workspacePath } = getConfig();
69
+ const base = basename(workspacePath);
70
+ _rootCache = base === "assistme" ? workspacePath : join(workspacePath, "assistme");
71
+ if (!existsSync(_rootCache)) {
72
+ mkdirSync(_rootCache, { recursive: true });
73
+ }
74
+ return _rootCache;
75
+ }
76
+ function getDataDir() {
77
+ if (_dataDirCache) return _dataDirCache;
78
+ const dataDir = join(getAssistMeRoot(), DATA_DIR_NAME);
79
+ if (!existsSync(dataDir)) {
80
+ mkdirSync(dataDir, { recursive: true, mode: 448 });
81
+ }
82
+ _dataDirCache = dataDir;
83
+ return dataDir;
84
+ }
85
+ function assertWithinAssistMeRoot(filePath) {
86
+ const root = getAssistMeRoot();
87
+ const resolved = resolve(root, filePath);
88
+ const rel = relative(root, resolved);
89
+ if (rel.startsWith("..") || rel.startsWith(sep + sep)) {
90
+ throw new AppError(
91
+ `Access denied: path "${filePath}" is outside assistme workspace "${root}"`,
92
+ "PATH_TRAVERSAL"
93
+ );
94
+ }
95
+ return resolved;
96
+ }
97
+ function resetDirCaches() {
98
+ _rootCache = null;
99
+ _dataDirCache = null;
100
+ }
101
+
102
+ export {
103
+ AppError,
104
+ errorMessage,
105
+ getConfig,
106
+ setConfig,
107
+ clearConfig,
108
+ getConfigPath,
109
+ getAssistMeRoot,
110
+ getDataDir,
111
+ assertWithinAssistMeRoot,
112
+ resetDirCaches
113
+ };