@heylemon/lemonade 0.6.8 → 0.7.0

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 (146) hide show
  1. package/dist/agents/model-fallback.js +7 -2
  2. package/dist/agents/pi-tool-definition-adapter.js +83 -10
  3. package/dist/agents/system-prompt.js +20 -1
  4. package/dist/auto-reply/reply/session.js +34 -8
  5. package/dist/build-info.json +3 -3
  6. package/dist/canvas-host/a2ui/.bundle.hash +1 -0
  7. package/dist/canvas-host/a2ui/a2ui.bundle.js +17775 -0
  8. package/dist/canvas-host/a2ui/index.html +307 -0
  9. package/dist/control-ui/assets/{index-0MsyRFLD.js → index-D5pbk0Cx.js} +261 -261
  10. package/dist/control-ui/assets/index-D5pbk0Cx.js.map +1 -0
  11. package/dist/control-ui/index.html +1 -1
  12. package/dist/gateway/auth-rate-limit.js +121 -0
  13. package/dist/gateway/auth.js +26 -8
  14. package/dist/gateway/server-http.js +7 -4
  15. package/dist/gateway/session-utils.fs.js +18 -0
  16. package/dist/gateway/skills-http.js +65 -0
  17. package/dist/security/secret-equal.js +13 -0
  18. package/extensions/diagnostics-otel/node_modules/.bin/acorn +2 -2
  19. package/extensions/googlechat/node_modules/.bin/lemonade +2 -2
  20. package/extensions/line/node_modules/.bin/lemonade +2 -2
  21. package/extensions/matrix/node_modules/.bin/lemonade +2 -2
  22. package/extensions/matrix/node_modules/.bin/markdown-it +2 -2
  23. package/extensions/memory-core/node_modules/.bin/lemonade +2 -2
  24. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +2 -2
  25. package/extensions/memory-lancedb/node_modules/.bin/openai +2 -2
  26. package/extensions/msteams/node_modules/.bin/lemonade +2 -2
  27. package/extensions/nostr/node_modules/.bin/lemonade +2 -2
  28. package/extensions/nostr/node_modules/.bin/tsc +2 -2
  29. package/extensions/nostr/node_modules/.bin/tsserver +2 -2
  30. package/extensions/twitch/node_modules/.bin/lemonade +2 -2
  31. package/extensions/zalo/node_modules/.bin/lemonade +2 -2
  32. package/extensions/zalouser/node_modules/.bin/lemonade +2 -2
  33. package/package.json +1 -1
  34. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  35. package/skills/travel-agent-persona/SKILL.md +89 -0
  36. package/dist/control-ui/assets/index-0MsyRFLD.js.map +0 -1
  37. package/extensions/googlechat/node_modules/.bin/lemon-calendar +0 -21
  38. package/extensions/googlechat/node_modules/.bin/lemon-cron +0 -21
  39. package/extensions/googlechat/node_modules/.bin/lemon-docs +0 -21
  40. package/extensions/googlechat/node_modules/.bin/lemon-drive +0 -21
  41. package/extensions/googlechat/node_modules/.bin/lemon-gmail +0 -21
  42. package/extensions/googlechat/node_modules/.bin/lemon-jira +0 -21
  43. package/extensions/googlechat/node_modules/.bin/lemon-notion +0 -21
  44. package/extensions/googlechat/node_modules/.bin/lemon-sheets +0 -21
  45. package/extensions/googlechat/node_modules/.bin/lemon-slack +0 -21
  46. package/extensions/googlechat/node_modules/.bin/lemon-slides +0 -21
  47. package/extensions/googlechat/node_modules/.bin/lemon-twitter +0 -21
  48. package/extensions/googlechat/node_modules/.bin/lemon-youtube +0 -21
  49. package/extensions/line/node_modules/.bin/lemon-calendar +0 -21
  50. package/extensions/line/node_modules/.bin/lemon-cron +0 -21
  51. package/extensions/line/node_modules/.bin/lemon-docs +0 -21
  52. package/extensions/line/node_modules/.bin/lemon-drive +0 -21
  53. package/extensions/line/node_modules/.bin/lemon-gmail +0 -21
  54. package/extensions/line/node_modules/.bin/lemon-jira +0 -21
  55. package/extensions/line/node_modules/.bin/lemon-notion +0 -21
  56. package/extensions/line/node_modules/.bin/lemon-sheets +0 -21
  57. package/extensions/line/node_modules/.bin/lemon-slack +0 -21
  58. package/extensions/line/node_modules/.bin/lemon-slides +0 -21
  59. package/extensions/line/node_modules/.bin/lemon-twitter +0 -21
  60. package/extensions/line/node_modules/.bin/lemon-youtube +0 -21
  61. package/extensions/matrix/node_modules/.bin/lemon-calendar +0 -21
  62. package/extensions/matrix/node_modules/.bin/lemon-cron +0 -21
  63. package/extensions/matrix/node_modules/.bin/lemon-docs +0 -21
  64. package/extensions/matrix/node_modules/.bin/lemon-drive +0 -21
  65. package/extensions/matrix/node_modules/.bin/lemon-gmail +0 -21
  66. package/extensions/matrix/node_modules/.bin/lemon-jira +0 -21
  67. package/extensions/matrix/node_modules/.bin/lemon-notion +0 -21
  68. package/extensions/matrix/node_modules/.bin/lemon-sheets +0 -21
  69. package/extensions/matrix/node_modules/.bin/lemon-slack +0 -21
  70. package/extensions/matrix/node_modules/.bin/lemon-slides +0 -21
  71. package/extensions/matrix/node_modules/.bin/lemon-twitter +0 -21
  72. package/extensions/matrix/node_modules/.bin/lemon-youtube +0 -21
  73. package/extensions/memory-core/node_modules/.bin/lemon-calendar +0 -21
  74. package/extensions/memory-core/node_modules/.bin/lemon-cron +0 -21
  75. package/extensions/memory-core/node_modules/.bin/lemon-docs +0 -21
  76. package/extensions/memory-core/node_modules/.bin/lemon-drive +0 -21
  77. package/extensions/memory-core/node_modules/.bin/lemon-gmail +0 -21
  78. package/extensions/memory-core/node_modules/.bin/lemon-jira +0 -21
  79. package/extensions/memory-core/node_modules/.bin/lemon-notion +0 -21
  80. package/extensions/memory-core/node_modules/.bin/lemon-sheets +0 -21
  81. package/extensions/memory-core/node_modules/.bin/lemon-slack +0 -21
  82. package/extensions/memory-core/node_modules/.bin/lemon-slides +0 -21
  83. package/extensions/memory-core/node_modules/.bin/lemon-twitter +0 -21
  84. package/extensions/memory-core/node_modules/.bin/lemon-youtube +0 -21
  85. package/extensions/msteams/node_modules/.bin/lemon-calendar +0 -21
  86. package/extensions/msteams/node_modules/.bin/lemon-cron +0 -21
  87. package/extensions/msteams/node_modules/.bin/lemon-docs +0 -21
  88. package/extensions/msteams/node_modules/.bin/lemon-drive +0 -21
  89. package/extensions/msteams/node_modules/.bin/lemon-gmail +0 -21
  90. package/extensions/msteams/node_modules/.bin/lemon-jira +0 -21
  91. package/extensions/msteams/node_modules/.bin/lemon-notion +0 -21
  92. package/extensions/msteams/node_modules/.bin/lemon-sheets +0 -21
  93. package/extensions/msteams/node_modules/.bin/lemon-slack +0 -21
  94. package/extensions/msteams/node_modules/.bin/lemon-slides +0 -21
  95. package/extensions/msteams/node_modules/.bin/lemon-twitter +0 -21
  96. package/extensions/msteams/node_modules/.bin/lemon-youtube +0 -21
  97. package/extensions/nostr/node_modules/.bin/lemon-calendar +0 -21
  98. package/extensions/nostr/node_modules/.bin/lemon-cron +0 -21
  99. package/extensions/nostr/node_modules/.bin/lemon-docs +0 -21
  100. package/extensions/nostr/node_modules/.bin/lemon-drive +0 -21
  101. package/extensions/nostr/node_modules/.bin/lemon-gmail +0 -21
  102. package/extensions/nostr/node_modules/.bin/lemon-jira +0 -21
  103. package/extensions/nostr/node_modules/.bin/lemon-notion +0 -21
  104. package/extensions/nostr/node_modules/.bin/lemon-sheets +0 -21
  105. package/extensions/nostr/node_modules/.bin/lemon-slack +0 -21
  106. package/extensions/nostr/node_modules/.bin/lemon-slides +0 -21
  107. package/extensions/nostr/node_modules/.bin/lemon-twitter +0 -21
  108. package/extensions/nostr/node_modules/.bin/lemon-youtube +0 -21
  109. package/extensions/twitch/node_modules/.bin/lemon-calendar +0 -21
  110. package/extensions/twitch/node_modules/.bin/lemon-cron +0 -21
  111. package/extensions/twitch/node_modules/.bin/lemon-docs +0 -21
  112. package/extensions/twitch/node_modules/.bin/lemon-drive +0 -21
  113. package/extensions/twitch/node_modules/.bin/lemon-gmail +0 -21
  114. package/extensions/twitch/node_modules/.bin/lemon-jira +0 -21
  115. package/extensions/twitch/node_modules/.bin/lemon-notion +0 -21
  116. package/extensions/twitch/node_modules/.bin/lemon-sheets +0 -21
  117. package/extensions/twitch/node_modules/.bin/lemon-slack +0 -21
  118. package/extensions/twitch/node_modules/.bin/lemon-slides +0 -21
  119. package/extensions/twitch/node_modules/.bin/lemon-twitter +0 -21
  120. package/extensions/twitch/node_modules/.bin/lemon-youtube +0 -21
  121. package/extensions/zalo/node_modules/.bin/lemon-calendar +0 -21
  122. package/extensions/zalo/node_modules/.bin/lemon-cron +0 -21
  123. package/extensions/zalo/node_modules/.bin/lemon-docs +0 -21
  124. package/extensions/zalo/node_modules/.bin/lemon-drive +0 -21
  125. package/extensions/zalo/node_modules/.bin/lemon-gmail +0 -21
  126. package/extensions/zalo/node_modules/.bin/lemon-jira +0 -21
  127. package/extensions/zalo/node_modules/.bin/lemon-notion +0 -21
  128. package/extensions/zalo/node_modules/.bin/lemon-sheets +0 -21
  129. package/extensions/zalo/node_modules/.bin/lemon-slack +0 -21
  130. package/extensions/zalo/node_modules/.bin/lemon-slides +0 -21
  131. package/extensions/zalo/node_modules/.bin/lemon-twitter +0 -21
  132. package/extensions/zalo/node_modules/.bin/lemon-youtube +0 -21
  133. package/extensions/zalouser/node_modules/.bin/lemon-calendar +0 -21
  134. package/extensions/zalouser/node_modules/.bin/lemon-cron +0 -21
  135. package/extensions/zalouser/node_modules/.bin/lemon-docs +0 -21
  136. package/extensions/zalouser/node_modules/.bin/lemon-drive +0 -21
  137. package/extensions/zalouser/node_modules/.bin/lemon-gmail +0 -21
  138. package/extensions/zalouser/node_modules/.bin/lemon-jira +0 -21
  139. package/extensions/zalouser/node_modules/.bin/lemon-notion +0 -21
  140. package/extensions/zalouser/node_modules/.bin/lemon-sheets +0 -21
  141. package/extensions/zalouser/node_modules/.bin/lemon-slack +0 -21
  142. package/extensions/zalouser/node_modules/.bin/lemon-slides +0 -21
  143. package/extensions/zalouser/node_modules/.bin/lemon-twitter +0 -21
  144. package/extensions/zalouser/node_modules/.bin/lemon-youtube +0 -21
  145. /package/skills/pdf/{FORMS.md → forms.md} +0 -0
  146. /package/skills/pdf/{REFERENCE.md → reference.md} +0 -0
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" type="image/svg+xml" href="./favicon.svg" />
9
9
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
10
10
  <link rel="apple-touch-icon" sizes="180x180" href="./apple-touch-icon.png" />
11
- <script type="module" crossorigin src="./assets/index-0MsyRFLD.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-D5pbk0Cx.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="./assets/index-BKPyesll.css">
13
13
  </head>
14
14
  <body>
@@ -0,0 +1,121 @@
1
+ /**
2
+ * In-memory sliding-window rate limiter for gateway authentication attempts.
3
+ *
4
+ * Tracks failed auth attempts by {scope, clientIp}. A scope lets callers keep
5
+ * independent counters for different credential classes (e.g. shared gateway
6
+ * token/password vs device-token auth) while sharing one limiter instance.
7
+ *
8
+ * Loopback addresses (127.0.0.1 / ::1) are exempt by default so that local
9
+ * CLI sessions and the native macOS app are never locked out.
10
+ */
11
+ import { isLoopbackAddress, resolveGatewayClientIp } from "./net.js";
12
+ export const AUTH_RATE_LIMIT_SCOPE_DEFAULT = "default";
13
+ export const AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET = "shared-secret";
14
+ export const AUTH_RATE_LIMIT_SCOPE_DEVICE_TOKEN = "device-token";
15
+ export const AUTH_RATE_LIMIT_SCOPE_HOOK_AUTH = "hook-auth";
16
+ // ---------------------------------------------------------------------------
17
+ // Defaults
18
+ // ---------------------------------------------------------------------------
19
+ const DEFAULT_MAX_ATTEMPTS = 10;
20
+ const DEFAULT_WINDOW_MS = 60_000;
21
+ const DEFAULT_LOCKOUT_MS = 300_000;
22
+ const PRUNE_INTERVAL_MS = 60_000;
23
+ // ---------------------------------------------------------------------------
24
+ // Implementation
25
+ // ---------------------------------------------------------------------------
26
+ export function normalizeRateLimitClientIp(ip) {
27
+ return resolveGatewayClientIp({ remoteAddr: ip ?? "" }) ?? "unknown";
28
+ }
29
+ export function createAuthRateLimiter(config) {
30
+ const maxAttempts = config?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
31
+ const windowMs = config?.windowMs ?? DEFAULT_WINDOW_MS;
32
+ const lockoutMs = config?.lockoutMs ?? DEFAULT_LOCKOUT_MS;
33
+ const exemptLoopback = config?.exemptLoopback ?? true;
34
+ const pruneIntervalMs = config?.pruneIntervalMs ?? PRUNE_INTERVAL_MS;
35
+ const entries = new Map();
36
+ const pruneTimer = pruneIntervalMs > 0 ? setInterval(() => prune(), pruneIntervalMs) : null;
37
+ if (pruneTimer?.unref) {
38
+ pruneTimer.unref();
39
+ }
40
+ function normalizeScope(scope) {
41
+ return (scope ?? AUTH_RATE_LIMIT_SCOPE_DEFAULT).trim() || AUTH_RATE_LIMIT_SCOPE_DEFAULT;
42
+ }
43
+ function normalizeIp(ip) {
44
+ return normalizeRateLimitClientIp(ip);
45
+ }
46
+ function resolveKey(rawIp, rawScope) {
47
+ const ip = normalizeIp(rawIp);
48
+ const scope = normalizeScope(rawScope);
49
+ return { key: `${scope}:${ip}`, ip };
50
+ }
51
+ function isExempt(ip) {
52
+ return exemptLoopback && isLoopbackAddress(ip);
53
+ }
54
+ function slideWindow(entry, now) {
55
+ const cutoff = now - windowMs;
56
+ entry.attempts = entry.attempts.filter((ts) => ts > cutoff);
57
+ }
58
+ function check(rawIp, rawScope) {
59
+ const { key, ip } = resolveKey(rawIp, rawScope);
60
+ if (isExempt(ip)) {
61
+ return { allowed: true, remaining: maxAttempts, retryAfterMs: 0 };
62
+ }
63
+ const now = Date.now();
64
+ const entry = entries.get(key);
65
+ if (!entry) {
66
+ return { allowed: true, remaining: maxAttempts, retryAfterMs: 0 };
67
+ }
68
+ if (entry.lockedUntil && now < entry.lockedUntil) {
69
+ return { allowed: false, remaining: 0, retryAfterMs: entry.lockedUntil - now };
70
+ }
71
+ if (entry.lockedUntil && now >= entry.lockedUntil) {
72
+ entry.lockedUntil = undefined;
73
+ entry.attempts = [];
74
+ }
75
+ slideWindow(entry, now);
76
+ const remaining = Math.max(0, maxAttempts - entry.attempts.length);
77
+ return { allowed: remaining > 0, remaining, retryAfterMs: 0 };
78
+ }
79
+ function recordFailure(rawIp, rawScope) {
80
+ const { key, ip } = resolveKey(rawIp, rawScope);
81
+ if (isExempt(ip))
82
+ return;
83
+ const now = Date.now();
84
+ let entry = entries.get(key);
85
+ if (!entry) {
86
+ entry = { attempts: [] };
87
+ entries.set(key, entry);
88
+ }
89
+ if (entry.lockedUntil && now < entry.lockedUntil)
90
+ return;
91
+ slideWindow(entry, now);
92
+ entry.attempts.push(now);
93
+ if (entry.attempts.length >= maxAttempts) {
94
+ entry.lockedUntil = now + lockoutMs;
95
+ }
96
+ }
97
+ function reset(rawIp, rawScope) {
98
+ const { key } = resolveKey(rawIp, rawScope);
99
+ entries.delete(key);
100
+ }
101
+ function prune() {
102
+ const now = Date.now();
103
+ for (const [key, entry] of entries) {
104
+ if (entry.lockedUntil && now < entry.lockedUntil)
105
+ continue;
106
+ slideWindow(entry, now);
107
+ if (entry.attempts.length === 0) {
108
+ entries.delete(key);
109
+ }
110
+ }
111
+ }
112
+ function size() {
113
+ return entries.size;
114
+ }
115
+ function dispose() {
116
+ if (pruneTimer)
117
+ clearInterval(pruneTimer);
118
+ entries.clear();
119
+ }
120
+ return { check, recordFailure, reset, size, prune, dispose };
121
+ }
@@ -1,11 +1,7 @@
1
- import { timingSafeEqual } from "node:crypto";
2
1
  import { readTailscaleWhoisIdentity } from "../infra/tailscale.js";
2
+ import { safeEqualSecret } from "../security/secret-equal.js";
3
+ import { AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET, } from "./auth-rate-limit.js";
3
4
  import { isTrustedProxyAddress, parseForwardedForClientIp, resolveGatewayClientIp } from "./net.js";
4
- function safeEqual(a, b) {
5
- if (a.length !== b.length)
6
- return false;
7
- return timingSafeEqual(Buffer.from(a), Buffer.from(b));
8
- }
9
5
  function normalizeLogin(login) {
10
6
  return login.trim().toLowerCase();
11
7
  }
@@ -155,12 +151,27 @@ export async function authorizeGatewayConnect(params) {
155
151
  const { auth, connectAuth, req, trustedProxies } = params;
156
152
  const tailscaleWhois = params.tailscaleWhois ?? readTailscaleWhoisIdentity;
157
153
  const localDirect = isLocalDirectRequest(req, trustedProxies);
154
+ const limiter = params.rateLimiter;
155
+ const ip = params.clientIp ?? resolveRequestClientIp(req, trustedProxies) ?? req?.socket?.remoteAddress;
156
+ const rateLimitScope = params.rateLimitScope ?? AUTH_RATE_LIMIT_SCOPE_SHARED_SECRET;
157
+ if (limiter) {
158
+ const rlCheck = limiter.check(ip, rateLimitScope);
159
+ if (!rlCheck.allowed) {
160
+ return {
161
+ ok: false,
162
+ reason: "rate_limited",
163
+ rateLimited: true,
164
+ retryAfterMs: rlCheck.retryAfterMs,
165
+ };
166
+ }
167
+ }
158
168
  if (auth.allowTailscale && !localDirect) {
159
169
  const tailscaleCheck = await resolveVerifiedTailscaleUser({
160
170
  req,
161
171
  tailscaleWhois,
162
172
  });
163
173
  if (tailscaleCheck.ok) {
174
+ limiter?.reset(ip, rateLimitScope);
164
175
  return {
165
176
  ok: true,
166
177
  method: "tailscale",
@@ -173,11 +184,14 @@ export async function authorizeGatewayConnect(params) {
173
184
  return { ok: false, reason: "token_missing_config" };
174
185
  }
175
186
  if (!connectAuth?.token) {
187
+ limiter?.recordFailure(ip, rateLimitScope);
176
188
  return { ok: false, reason: "token_missing" };
177
189
  }
178
- if (!safeEqual(connectAuth.token, auth.token)) {
190
+ if (!safeEqualSecret(connectAuth.token, auth.token)) {
191
+ limiter?.recordFailure(ip, rateLimitScope);
179
192
  return { ok: false, reason: "token_mismatch" };
180
193
  }
194
+ limiter?.reset(ip, rateLimitScope);
181
195
  return { ok: true, method: "token" };
182
196
  }
183
197
  if (auth.mode === "password") {
@@ -186,12 +200,16 @@ export async function authorizeGatewayConnect(params) {
186
200
  return { ok: false, reason: "password_missing_config" };
187
201
  }
188
202
  if (!password) {
203
+ limiter?.recordFailure(ip, rateLimitScope);
189
204
  return { ok: false, reason: "password_missing" };
190
205
  }
191
- if (!safeEqual(password, auth.password)) {
206
+ if (!safeEqualSecret(password, auth.password)) {
207
+ limiter?.recordFailure(ip, rateLimitScope);
192
208
  return { ok: false, reason: "password_mismatch" };
193
209
  }
210
+ limiter?.reset(ip, rateLimitScope);
194
211
  return { ok: true, method: "password" };
195
212
  }
213
+ limiter?.recordFailure(ip, rateLimitScope);
196
214
  return { ok: false, reason: "unauthorized" };
197
215
  }
@@ -13,6 +13,7 @@ import { handleSkillsHttpRequest } from "./skills-http.js";
13
13
  import { handleTaskEventsHttpRequest } from "./task-events-http.js";
14
14
  import { handleToolsInvokeHttpRequest } from "./tools-invoke-http.js";
15
15
  import { handleCronHttpRequest } from "./cron-http.js";
16
+ import { safeEqualSecret } from "../security/secret-equal.js";
16
17
  function sendJson(res, status, body) {
17
18
  res.statusCode = status;
18
19
  res.setHeader("Content-Type", "application/json; charset=utf-8");
@@ -30,16 +31,18 @@ export function createHooksRequestHandler(opts) {
30
31
  return false;
31
32
  }
32
33
  const { token, fromQuery } = extractHookToken(req, url);
33
- if (!token || token !== hooksConfig.token) {
34
+ if (!token || !safeEqualSecret(token, hooksConfig.token)) {
34
35
  res.statusCode = 401;
35
36
  res.setHeader("Content-Type", "text/plain; charset=utf-8");
36
37
  res.end("Unauthorized");
37
38
  return true;
38
39
  }
39
40
  if (fromQuery) {
40
- logHooks.warn("Hook token provided via query parameter is deprecated for security reasons. " +
41
- "Tokens in URLs appear in logs, browser history, and referrer headers. " +
42
- "Use Authorization: Bearer <token> or X-Lemonade-Token header instead.");
41
+ sendJson(res, 400, {
42
+ error: "Hook token via query parameter is no longer supported. " +
43
+ "Use Authorization: Bearer <token> or X-Lemonade-Token header instead.",
44
+ });
45
+ return true;
43
46
  }
44
47
  if (req.method !== "POST") {
45
48
  res.statusCode = 405;
@@ -46,6 +46,24 @@ export function archiveFileOnDisk(filePath, reason) {
46
46
  fs.renameSync(filePath, archived);
47
47
  return archived;
48
48
  }
49
+ /**
50
+ * Archives all transcript files for a given session.
51
+ * Best-effort: silently skips files that don't exist or fail to rename.
52
+ */
53
+ export function archiveSessionTranscripts(opts) {
54
+ const archived = [];
55
+ for (const candidate of resolveSessionTranscriptCandidates(opts.sessionId, opts.storePath, opts.sessionFile, opts.agentId)) {
56
+ if (!fs.existsSync(candidate))
57
+ continue;
58
+ try {
59
+ archived.push(archiveFileOnDisk(candidate, opts.reason));
60
+ }
61
+ catch {
62
+ // Best-effort.
63
+ }
64
+ }
65
+ return archived;
66
+ }
49
67
  function jsonUtf8Bytes(value) {
50
68
  try {
51
69
  return Buffer.byteLength(JSON.stringify(value), "utf8");
@@ -89,6 +89,22 @@ export async function handleSkillsHttpRequest(req, res, opts) {
89
89
  return true;
90
90
  }
91
91
  }
92
+ if (url.pathname === "/api/skills/install-pack" || url.pathname === "/api/skills/install-pack/") {
93
+ if (req.method !== "POST") {
94
+ sendMethodNotAllowed(res, "POST");
95
+ return true;
96
+ }
97
+ try {
98
+ return await handleSkillsInstallPack(req, res);
99
+ }
100
+ catch (err) {
101
+ console.error("[skills-http] Install-pack error:", err);
102
+ sendJson(res, 500, {
103
+ error: { message: "An internal error occurred", type: "internal_error" },
104
+ });
105
+ return true;
106
+ }
107
+ }
92
108
  // Parse the skill name from the URL
93
109
  const pathParts = url.pathname
94
110
  .replace(/^\/api\/skills\/?/, "")
@@ -399,6 +415,55 @@ async function handleSkillsInstall(req, res) {
399
415
  sendJson(res, result.ok ? 200 : 500, result);
400
416
  return true;
401
417
  }
418
+ async function handleSkillsInstallPack(req, res) {
419
+ const body = (await readJsonBodyOrError(req, res, 100_000));
420
+ if (!body)
421
+ return true;
422
+ const skillNames = Array.isArray(body.skillNames) ? body.skillNames.filter(Boolean) : [];
423
+ if (skillNames.length === 0) {
424
+ sendInvalidRequest(res, "skillNames array is required");
425
+ return true;
426
+ }
427
+ const cfg = loadConfig();
428
+ const workspaceDir = resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg));
429
+ const report = buildWorkspaceSkillStatus(workspaceDir, {
430
+ config: cfg,
431
+ eligibility: { remote: getRemoteSkillEligibility() },
432
+ });
433
+ const toInstall = [];
434
+ for (const s of report.skills) {
435
+ if (!skillNames.includes(s.name))
436
+ continue;
437
+ if (!s.missing?.bins?.length)
438
+ continue;
439
+ const firstInstall = s.install?.[0];
440
+ if (firstInstall?.id) {
441
+ toInstall.push({ skillName: s.name, installId: firstInstall.id });
442
+ }
443
+ }
444
+ if (toInstall.length === 0) {
445
+ sendJson(res, 200, { ok: true, installed: [], message: "Nothing to install" });
446
+ return true;
447
+ }
448
+ // Respond immediately — installations happen in background
449
+ sendJson(res, 202, {
450
+ ok: true,
451
+ installing: toInstall.map((t) => t.skillName),
452
+ message: `Installing dependencies for ${toInstall.length} skill(s) in background`,
453
+ });
454
+ // Fire-and-forget background installs
455
+ for (const item of toInstall) {
456
+ installSkill({
457
+ workspaceDir,
458
+ skillName: item.skillName,
459
+ installId: item.installId,
460
+ config: cfg,
461
+ }).catch((err) => {
462
+ console.error(`[skills-http] Background install failed for ${item.skillName}:`, err);
463
+ });
464
+ }
465
+ return true;
466
+ }
402
467
  async function handleDeleteSkill(res, skillName) {
403
468
  const builtInNames = getBuiltInSkillNames();
404
469
  if (builtInNames.has(skillName)) {
@@ -0,0 +1,13 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ /**
3
+ * Constant-time secret comparison that avoids leaking length information.
4
+ * Both values are SHA-256 hashed before comparison so `timingSafeEqual`
5
+ * always operates on equal-length buffers regardless of input lengths.
6
+ */
7
+ export function safeEqualSecret(provided, expected) {
8
+ if (typeof provided !== "string" || typeof expected !== "string") {
9
+ return false;
10
+ }
11
+ const hash = (s) => createHash("sha256").update(s).digest();
12
+ return timingSafeEqual(hash(provided), hash(expected));
13
+ }
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/acorn@8.15.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/acorn@8.15.0/node_modules/acorn/bin/acorn" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules/markdown-it/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/markdown-it@14.1.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../markdown-it/bin/markdown-it.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/apache-arrow@18.1.0/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/apache-arrow@18.1.0/node_modules/apache-arrow/bin/arrow2csv.js" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules/openai/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules/openai/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules/openai/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules/openai/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/openai@6.17.0_ws@8.19.0_zod@4.3.6/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../openai/bin/cli" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/typescript@5.9.3/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"
@@ -10,9 +10,9 @@ case `uname` in
10
10
  esac
11
11
 
12
12
  if [ -z "$NODE_PATH" ]; then
13
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules"
13
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules"
14
14
  else
15
- export NODE_PATH="/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/node_modules:/Users/masoodshakir/Documents/fpl_repos/node_modules:/Users/masoodshakir/Documents/node_modules:/Users/masoodshakir/node_modules:/Users/node_modules:/node_modules:/Users/masoodshakir/Documents/fpl_repos/voice/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
15
+ export NODE_PATH="/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules:/Users/futureprooflabs/Desktop/clawdbot/node_modules:/Users/futureprooflabs/Desktop/node_modules:/Users/futureprooflabs/node_modules:/Users/node_modules:/node_modules:/Users/futureprooflabs/Desktop/clawdbot/lemonade/node_modules/.pnpm/node_modules:$NODE_PATH"
16
16
  fi
17
17
  if [ -x "$basedir/node" ]; then
18
18
  exec "$basedir/node" "$basedir/../lemonade/lemonade.mjs" "$@"