alvin-bot 5.7.0 → 5.8.1
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.
- package/CHANGELOG.md +25 -0
- package/README.md +25 -31
- package/dist/claude.js +1 -102
- package/dist/config.js +1 -96
- package/dist/engine.js +1 -90
- package/dist/find-claude-binary.js +1 -98
- package/dist/handlers/async-agent-chunk-handler.js +1 -50
- package/dist/handlers/background-bypass.js +1 -75
- package/dist/handlers/commands.js +1 -2336
- package/dist/handlers/cron-progress.js +1 -52
- package/dist/handlers/document.js +1 -194
- package/dist/handlers/message.js +1 -959
- package/dist/handlers/photo.js +1 -154
- package/dist/handlers/platform-message.js +1 -360
- package/dist/handlers/stuck-timer.js +1 -54
- package/dist/handlers/video.js +1 -237
- package/dist/handlers/voice.js +1 -148
- package/dist/i18n.js +1 -805
- package/dist/index.js +1 -697
- package/dist/init-data-dir.js +1 -98
- package/dist/middleware/auth.js +1 -233
- package/dist/migrate.js +1 -162
- package/dist/paths.js +1 -146
- package/dist/platforms/discord.js +1 -175
- package/dist/platforms/index.js +1 -130
- package/dist/platforms/signal.js +1 -205
- package/dist/platforms/slack-slash-parser.js +1 -32
- package/dist/platforms/slack.js +1 -501
- package/dist/platforms/telegram.js +1 -111
- package/dist/platforms/types.js +1 -8
- package/dist/platforms/whatsapp-auth-helpers.js +1 -53
- package/dist/platforms/whatsapp.js +1 -707
- package/dist/providers/claude-sdk-provider.js +1 -565
- package/dist/providers/codex-cli-provider.js +1 -134
- package/dist/providers/index.js +1 -7
- package/dist/providers/ollama-provider.js +1 -32
- package/dist/providers/openai-compatible.js +1 -406
- package/dist/providers/registry.js +1 -352
- package/dist/providers/runtime-header.js +1 -45
- package/dist/providers/tool-executor.js +1 -475
- package/dist/providers/types.js +1 -227
- package/dist/services/access.js +1 -144
- package/dist/services/allowed-users-gate.js +1 -56
- package/dist/services/alvin-dispatch.js +1 -174
- package/dist/services/alvin-mcp-tools.js +1 -104
- package/dist/services/asset-index.js +1 -224
- package/dist/services/async-agent-parser.js +1 -418
- package/dist/services/async-agent-watcher.js +1 -583
- package/dist/services/auto-diagnostic.js +1 -228
- package/dist/services/broadcast.js +1 -52
- package/dist/services/browser-manager.js +1 -562
- package/dist/services/browser-webfetch.js +1 -127
- package/dist/services/browser.js +1 -121
- package/dist/services/cdp-bootstrap.js +1 -357
- package/dist/services/compaction.js +1 -144
- package/dist/services/critical-notify.js +1 -203
- package/dist/services/cron-resolver.js +1 -58
- package/dist/services/cron-scheduling.js +1 -310
- package/dist/services/cron.js +1 -861
- package/dist/services/custom-tools.js +1 -317
- package/dist/services/delivery-queue.js +1 -173
- package/dist/services/delivery-registry.js +1 -21
- package/dist/services/disk-cleanup.js +1 -203
- package/dist/services/elevenlabs.js +1 -58
- package/dist/services/embeddings/auto-detect.js +1 -74
- package/dist/services/embeddings/fts5.js +1 -108
- package/dist/services/embeddings/gemini.js +1 -65
- package/dist/services/embeddings/index.js +1 -496
- package/dist/services/embeddings/ollama.js +1 -78
- package/dist/services/embeddings/openai.js +1 -49
- package/dist/services/embeddings/provider.js +1 -22
- package/dist/services/embeddings/vector-base.js +1 -113
- package/dist/services/embeddings-migration.js +1 -193
- package/dist/services/embeddings.js +1 -9
- package/dist/services/env-file.js +1 -50
- package/dist/services/exec-guard.js +1 -71
- package/dist/services/fallback-order.js +1 -154
- package/dist/services/file-permissions.js +1 -93
- package/dist/services/heartbeat-file.js +1 -65
- package/dist/services/heartbeat.js +1 -313
- package/dist/services/hooks.js +1 -44
- package/dist/services/imagegen.js +1 -72
- package/dist/services/language-detect.js +1 -154
- package/dist/services/markdown.js +1 -63
- package/dist/services/mcp.js +1 -263
- package/dist/services/memory-extractor.js +1 -178
- package/dist/services/memory-inject-mode.js +1 -43
- package/dist/services/memory-layers.js +1 -156
- package/dist/services/memory.js +1 -146
- package/dist/services/ollama-manager.js +1 -339
- package/dist/services/permissions-wizard.js +1 -291
- package/dist/services/personality.js +1 -376
- package/dist/services/plugins.js +1 -171
- package/dist/services/preflight.js +1 -292
- package/dist/services/process-manager.js +1 -291
- package/dist/services/release-highlights.js +1 -79
- package/dist/services/reminders.js +1 -97
- package/dist/services/restart.js +1 -48
- package/dist/services/security-audit.js +1 -74
- package/dist/services/self-diagnosis.js +1 -272
- package/dist/services/self-search.js +1 -129
- package/dist/services/session-persistence.js +1 -237
- package/dist/services/session.js +1 -282
- package/dist/services/skills.js +1 -290
- package/dist/services/ssrf-guard.js +1 -162
- package/dist/services/standing-orders.js +1 -29
- package/dist/services/steer-channel.js +1 -46
- package/dist/services/stop-controller.js +1 -52
- package/dist/services/subagent-dedup.js +1 -86
- package/dist/services/subagent-delivery.js +1 -452
- package/dist/services/subagent-stats.js +1 -123
- package/dist/services/subagents.js +1 -814
- package/dist/services/sudo.js +1 -329
- package/dist/services/telegram.js +1 -158
- package/dist/services/timing-safe-bearer.js +1 -51
- package/dist/services/tool-discovery.js +1 -214
- package/dist/services/trends.js +1 -580
- package/dist/services/updater.js +1 -291
- package/dist/services/usage-tracker.js +1 -144
- package/dist/services/users.js +1 -271
- package/dist/services/voice.js +1 -104
- package/dist/services/watchdog-brake.js +1 -154
- package/dist/services/watchdog.js +1 -311
- package/dist/services/workspaces.js +1 -276
- package/dist/tui/index.js +1 -667
- package/dist/util/console-formatter.js +1 -109
- package/dist/util/debounce.js +1 -24
- package/dist/util/telegram-error-filter.js +1 -62
- package/dist/version.js +1 -24
- package/dist/web/bind-strategy.js +1 -42
- package/dist/web/canvas.js +1 -30
- package/dist/web/doctor-api.js +1 -604
- package/dist/web/openai-compat.js +1 -252
- package/dist/web/server.js +1 -1902
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
|
@@ -1,174 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* v4.13 — alvin_dispatch custom-tool service.
|
|
3
|
-
*
|
|
4
|
-
* Architectural replacement for Claude Agent SDK's built-in
|
|
5
|
-
* `Task(run_in_background: true)` tool. The SDK's built-in version
|
|
6
|
-
* ties the background sub-agent's execution to the parent SDK
|
|
7
|
-
* subprocess lifecycle — killing the parent (e.g. via v4.12.3's
|
|
8
|
-
* bypass-abort) cascades into killing any in-flight background tasks.
|
|
9
|
-
*
|
|
10
|
-
* This module instead spawns a truly independent `claude -p` subprocess
|
|
11
|
-
* via Node's `child_process.spawn({ detached: true, stdio: [...] })`.
|
|
12
|
-
* The subprocess:
|
|
13
|
-
* - Has its own PID, own process group (by detached: true)
|
|
14
|
-
* - Is unreffed so the parent Node process doesn't wait for it
|
|
15
|
-
* - Writes its stream-json output to its own file
|
|
16
|
-
* - Survives any abort/crash/restart of the parent Alvin bot
|
|
17
|
-
*
|
|
18
|
-
* The async-agent-watcher polls the output file and delivers the
|
|
19
|
-
* final result via subagent-delivery.ts when the sub-agent completes.
|
|
20
|
-
*
|
|
21
|
-
* See Phase A of docs/superpowers/plans/2026-04-16-v4.13-truly-async-subagents.md
|
|
22
|
-
* for the empirical verification that detached `claude -p` subprocesses
|
|
23
|
-
* behave as expected (they do).
|
|
24
|
-
*/
|
|
25
|
-
import { spawn } from "node:child_process";
|
|
26
|
-
import fs from "node:fs";
|
|
27
|
-
import crypto from "node:crypto";
|
|
28
|
-
import { resolve } from "node:path";
|
|
29
|
-
import { findClaudeBinary } from "../find-claude-binary.js";
|
|
30
|
-
import { registerPendingAgent } from "./async-agent-watcher.js";
|
|
31
|
-
import { getAllSessions } from "./session.js";
|
|
32
|
-
import { SUBAGENTS_DIR } from "../paths.js";
|
|
33
|
-
/** Generate a 32-char hex agent id. Avoids collisions across parallel
|
|
34
|
-
* dispatches even at sub-millisecond intervals. */
|
|
35
|
-
function generateAgentId() {
|
|
36
|
-
return "alvin-" + crypto.randomBytes(12).toString("hex");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* v5.7.0 — Best-effort push: tell the bot a detached sub-agent just
|
|
40
|
-
* exited so it can read the jsonl and deliver immediately instead of
|
|
41
|
-
* waiting for the next 15s poll tick. An in-process self-call to the
|
|
42
|
-
* always-on loopback route. Any failure (bot mid-restart, port race,
|
|
43
|
-
* network) is swallowed — startup reconciliation and the poll backstop
|
|
44
|
-
* are the safety nets. Never throws, always resolves.
|
|
45
|
-
*/
|
|
46
|
-
export async function postSubagentExit(agentId, exitCode) {
|
|
47
|
-
try {
|
|
48
|
-
const { getWebPort, getInternalToken } = await import("../web/server.js");
|
|
49
|
-
const port = getWebPort();
|
|
50
|
-
const token = getInternalToken();
|
|
51
|
-
const ac = new AbortController();
|
|
52
|
-
const timer = setTimeout(() => ac.abort(), 4000);
|
|
53
|
-
try {
|
|
54
|
-
await fetch(`http://127.0.0.1:${port}/internal/subagent-exit`, {
|
|
55
|
-
method: "POST",
|
|
56
|
-
headers: {
|
|
57
|
-
"Content-Type": "application/json",
|
|
58
|
-
Authorization: `Bearer ${token}`,
|
|
59
|
-
},
|
|
60
|
-
body: JSON.stringify({ agentId, exitCode }),
|
|
61
|
-
signal: ac.signal,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
finally {
|
|
65
|
-
clearTimeout(timer);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
/* best-effort — reconciliation/poll backstop cover any miss */
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Dispatch a detached sub-agent. Returns synchronously — the subprocess
|
|
74
|
-
* runs in the background. Throws if spawn fails. On success:
|
|
75
|
-
*
|
|
76
|
-
* 1. Subprocess is running, writing stream-json to outputFile
|
|
77
|
-
* 2. The agent is registered with async-agent-watcher (pending list)
|
|
78
|
-
* 3. session.pendingBackgroundCount is incremented
|
|
79
|
-
* 4. When the subprocess completes, watcher delivers the result
|
|
80
|
-
*/
|
|
81
|
-
export function dispatchDetachedAgent(input) {
|
|
82
|
-
// Ensure subagents dir exists. Idempotent.
|
|
83
|
-
try {
|
|
84
|
-
fs.mkdirSync(SUBAGENTS_DIR, { recursive: true });
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
/* race-safe — next open() will surface the real error */
|
|
88
|
-
}
|
|
89
|
-
const agentId = generateAgentId();
|
|
90
|
-
const outputFile = resolve(SUBAGENTS_DIR, `${agentId}.jsonl`);
|
|
91
|
-
// Open the output file for write. We pass the FD to child's stdout
|
|
92
|
-
// so the subprocess writes directly without going through us.
|
|
93
|
-
// stderr → separate .err file for diagnostics.
|
|
94
|
-
const errFile = resolve(SUBAGENTS_DIR, `${agentId}.err`);
|
|
95
|
-
const outFd = fs.openSync(outputFile, "w");
|
|
96
|
-
const errFd = fs.openSync(errFile, "w");
|
|
97
|
-
const cleanEnv = { ...process.env };
|
|
98
|
-
// v4.13 — Prevent nested-session errors. The SDK refuses to run if
|
|
99
|
-
// these are already set in env (they leak from parent Alvin/SDK).
|
|
100
|
-
delete cleanEnv.CLAUDECODE;
|
|
101
|
-
delete cleanEnv.CLAUDE_CODE_ENTRYPOINT;
|
|
102
|
-
const claudePath = findClaudeBinary();
|
|
103
|
-
if (!claudePath) {
|
|
104
|
-
fs.closeSync(outFd);
|
|
105
|
-
fs.closeSync(errFd);
|
|
106
|
-
throw new Error("alvin_dispatch: claude CLI not found. Install claude-code to enable background dispatch.");
|
|
107
|
-
}
|
|
108
|
-
const child = spawn(claudePath, [
|
|
109
|
-
"-p",
|
|
110
|
-
input.prompt,
|
|
111
|
-
"--output-format",
|
|
112
|
-
"stream-json",
|
|
113
|
-
"--verbose",
|
|
114
|
-
], {
|
|
115
|
-
cwd: input.cwd,
|
|
116
|
-
detached: true,
|
|
117
|
-
stdio: ["ignore", outFd, errFd],
|
|
118
|
-
env: cleanEnv,
|
|
119
|
-
});
|
|
120
|
-
// Close our copies of the FDs — the child has its own descriptors now.
|
|
121
|
-
try {
|
|
122
|
-
fs.closeSync(outFd);
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
/* ignore */
|
|
126
|
-
}
|
|
127
|
-
try {
|
|
128
|
-
fs.closeSync(errFd);
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
/* ignore */
|
|
132
|
-
}
|
|
133
|
-
// v5.7.0 — Push: deliver the result the instant the subprocess exits,
|
|
134
|
-
// instead of waiting for the next 15s poll tick. `exit` fires after
|
|
135
|
-
// the OS has reaped the process and flushed its inherited stdout FD,
|
|
136
|
-
// so the terminating result line is fully on disk before the handler
|
|
137
|
-
// reads it (race-safe). Best-effort: startup reconciliation + the poll
|
|
138
|
-
// backstop cover a missed push (bot restarted mid-run, port race).
|
|
139
|
-
// Attached before unref() so the listener is registered on the handle.
|
|
140
|
-
child.on("exit", (code) => {
|
|
141
|
-
void postSubagentExit(agentId, code);
|
|
142
|
-
});
|
|
143
|
-
// Detach from parent Node's event loop so parent exit doesn't wait.
|
|
144
|
-
child.unref();
|
|
145
|
-
// Register with watcher so it polls the output file and delivers.
|
|
146
|
-
// child.pid is captured here (before unref) so killSessionDetachedAgents
|
|
147
|
-
// can send SIGTERM to the process. child.pid may be undefined if the OS
|
|
148
|
-
// failed to assign a PID (extremely rare); registerPendingAgent tolerates it.
|
|
149
|
-
registerPendingAgent({
|
|
150
|
-
agentId,
|
|
151
|
-
outputFile,
|
|
152
|
-
description: input.description,
|
|
153
|
-
prompt: input.prompt,
|
|
154
|
-
chatId: input.chatId,
|
|
155
|
-
userId: input.userId,
|
|
156
|
-
toolUseId: null,
|
|
157
|
-
sessionKey: input.sessionKey,
|
|
158
|
-
platform: input.platform,
|
|
159
|
-
pid: child.pid,
|
|
160
|
-
});
|
|
161
|
-
// Increment the session's pendingBackgroundCount so the main handler
|
|
162
|
-
// knows a background task is in flight (same signal path as SDK's
|
|
163
|
-
// built-in Task tool).
|
|
164
|
-
try {
|
|
165
|
-
const s = getAllSessions().get(input.sessionKey);
|
|
166
|
-
if (s) {
|
|
167
|
-
s.pendingBackgroundCount = (s.pendingBackgroundCount ?? 0) + 1;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
catch {
|
|
171
|
-
/* never let counter updates break dispatch */
|
|
172
|
-
}
|
|
173
|
-
return { agentId, outputFile, spawned: true };
|
|
174
|
-
}
|
|
1
|
+
(function(_0x25ccc7,_0x43afe9){const _0x206207=_0x3c10,_0x148497=_0x3c10,_0xaf3266=_0x25ccc7();while(!![]){try{const _0x35fd44=parseInt(_0x206207(0x219))/(-0x2e3*-0x5+-0x262d+-0x1*-0x17bf)+-parseInt(_0x206207(0x21b))/(-0x1*0x12d4+0x1820+-0x54a)+parseInt(_0x148497(0x200))/(0x2d0+-0x739+0x46c)+-parseInt(_0x148497(0x205))/(0x2e6+-0x20a9+0x21*0xe7)*(-parseInt(_0x206207(0x1ec))/(0x1664+0x84e+-0x1ead))+parseInt(_0x206207(0x1f8))/(0x1478+0x1528+-0x299a)+parseInt(_0x148497(0x20d))/(0x1648+-0xcaa*-0x2+0xd*-0x3a9)*(parseInt(_0x206207(0x1eb))/(0x66*0x11+0x2*-0x57b+-0x1e*-0x24))+-parseInt(_0x206207(0x217))/(-0xb1f+-0x265e+-0x3*-0x1082);if(_0x35fd44===_0x43afe9)break;else _0xaf3266['push'](_0xaf3266['shift']());}catch(_0x4bfd54){_0xaf3266['push'](_0xaf3266['shift']());}}}(_0x1755,0x17bec+0x16047*-0x9+-0xeca7*-0x15));const _0x2b7faf=(function(){let _0x4f254d=!![];return function(_0x3d6186,_0x23a0bc){const _0x423f9b=_0x4f254d?function(){const _0x6b54f6=_0x3c10;if(_0x23a0bc){const _0x52796d=_0x23a0bc[_0x6b54f6(0x20b)](_0x3d6186,arguments);return _0x23a0bc=null,_0x52796d;}}:function(){};return _0x4f254d=![],_0x423f9b;};}()),_0x170932=_0x2b7faf(this,function(){const _0xca2bdb=_0x3c10,_0x455698=_0x3c10;return _0x170932[_0xca2bdb(0x206)]()[_0x455698(0x203)]('(((.+)+)+)'+'+$')[_0x455698(0x206)]()[_0xca2bdb(0x207)+'r'](_0x170932)['search'](_0xca2bdb(0x1fe)+'+$');});_0x170932();import{spawn}from'node:child_process';import _0x540009 from'node:fs';import _0x437d9c from'node:crypto';function _0x1755(){const _0x18a937=['CgLK','mtmZmJaZzKvvCg1k','BI9QC29U','C2LNBMfS','zguGq0Xjig5VDa','lMvYCG','ue9tva','C3vIywDLBNqTzq','C2vZC2LVBKTLEq','Ahr0CdOVlZeYnW','lI4VD2vIl3nLCG','mtK0otKXmtj0suP3D1K','C3rYAw5NAwz5','odaXode0ruX1shPq','C3rYzwfTlwPZBW','mJe2mZy5nfH0y3bNwq','yxrJAdOGy2XHDq','l2LUDgvYBMfSlW','B3bLBLn5BMm','mJG4uKPxs0nb','mJi1ntGWCM1hB0zk','igzVDw5KlIbjBG','AwDUB3jL','q0Xbvurfq09erq','EgL0','DMvYlMPZ','yxbWBgLJyxrPBW','y3DK','A2DYB3vUzenVDq','q0Xbvurfx0npra','y2TNCM91BMqGza','ChjVBxb0','ndm2mZG5mffpAfLNvW','y2XVC2vtEw5J','BwTKAxjtEw5J','CgXHDgzVCM0','CgvUzgLUz0jHyW','Agv4','kcGOlISPkYKRkq','Dw5Yzwy','mJq3ntm3ognPt21eDq','rv9ftLrswvbpsq','zxHPDa','C2vHCMnO','lJaUmc4XoG','nJHrAvPqB1O','Dg9tDhjPBMC','y29UC3rYDwn0BW','z2v0','ls12zxjIB3nL','ls1VDxrWDxqTzG','yxbWBhK'];_0x1755=function(){return _0x18a937;};return _0x1755();}import{resolve}from'node:path';import{findClaudeBinary}from'../find-claude-binary.js';function _0x3c10(_0x4b03bc,_0x39d301){_0x4b03bc=_0x4b03bc-(-0x111a+0x1127+0x1db);const _0x27cbe0=_0x1755();let _0xb68842=_0x27cbe0[_0x4b03bc];if(_0x3c10['yOFXDV']===undefined){var _0xe5b111=function(_0x1be015){const _0x922e61='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4ae20b='',_0x4e9a73='',_0x298487=_0x4ae20b+_0xe5b111;for(let _0x4f513c=-0x13f4+-0x2*-0x512+-0x9d*-0x10,_0xd441d3,_0x425a96,_0x3ca81b=-0xd*-0x6d+0x6*-0x17f+0x371;_0x425a96=_0x1be015['charAt'](_0x3ca81b++);~_0x425a96&&(_0xd441d3=_0x4f513c%(0xe*-0x11b+-0x2115+0x3093)?_0xd441d3*(0x95a+-0x1f52+0x24*0x9e)+_0x425a96:_0x425a96,_0x4f513c++%(-0x84f*-0x3+-0x11*0x242+0xd79))?_0x4ae20b+=_0x298487['charCodeAt'](_0x3ca81b+(0x1c*0x110+-0x239e+0x7e*0xc))-(-0x1*-0x665+-0x25a6+-0x1*-0x1f4b)!==0x4ae*-0x2+-0x130d+-0x7*-0x40f?String['fromCharCode'](0x5*-0x5ad+-0x1376+0x292*0x13&_0xd441d3>>(-(0x25e1*-0x1+-0xe72*-0x2+0x8ff)*_0x4f513c&-0x2ab+0x182a+0xef*-0x17)):_0x4f513c:-0xb*0x309+-0x1*-0x64c+0x1b17*0x1){_0x425a96=_0x922e61['indexOf'](_0x425a96);}for(let _0x37f531=-0xa34+-0x23e4+-0x170c*-0x2,_0x224f7f=_0x4ae20b['length'];_0x37f531<_0x224f7f;_0x37f531++){_0x4e9a73+='%'+('00'+_0x4ae20b['charCodeAt'](_0x37f531)['toString'](-0x1a47+-0x5*-0x43e+-0x65*-0xd))['slice'](-(0x25fa+-0x13*-0x139+-0x3d33));}return decodeURIComponent(_0x4e9a73);};_0x3c10['lyKFWN']=_0xe5b111,_0x3c10['WxpKUW']={},_0x3c10['yOFXDV']=!![];}const _0x48aba1=_0x27cbe0[0x8*0x147+0x10c1*-0x1+0x689],_0x498242=_0x4b03bc+_0x48aba1,_0xf92fb7=_0x3c10['WxpKUW'][_0x498242];if(!_0xf92fb7){const _0x327f77=function(_0x4baf2d){this['GCnnaf']=_0x4baf2d,this['DKdpDq']=[-0x12a3*-0x2+0xe4d*-0x2+-0x8ab,0x4*-0x542+0x2d*0x55+0x1*0x617,-0x1*0x9da+0xc92+0x8*-0x57],this['JedqPH']=function(){return'newState';},this['RymcGO']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['cyOQkG']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x327f77['prototype']['zqBmAO']=function(){const _0x4ec772=new RegExp(this['RymcGO']+this['cyOQkG']),_0x3a290d=_0x4ec772['test'](this['JedqPH']['toString']())?--this['DKdpDq'][-0x262d+0x212b+-0x1*-0x503]:--this['DKdpDq'][-0x1*0x12d4+0x1820+-0x54c];return this['ziIpai'](_0x3a290d);},_0x327f77['prototype']['ziIpai']=function(_0x368074){if(!Boolean(~_0x368074))return _0x368074;return this['nPQvWq'](this['GCnnaf']);},_0x327f77['prototype']['nPQvWq']=function(_0x17f2d3){for(let _0x221ce4=0x2d0+-0x739+0x469,_0xdc00f=this['DKdpDq']['length'];_0x221ce4<_0xdc00f;_0x221ce4++){this['DKdpDq']['push'](Math['round'](Math['random']())),_0xdc00f=this['DKdpDq']['length'];}return _0x17f2d3(this['DKdpDq'][0x2e6+-0x20a9+0x13*0x191]);},new _0x327f77(_0x3c10)['zqBmAO'](),_0xb68842=_0x3c10['lyKFWN'](_0xb68842),_0x3c10['WxpKUW'][_0x498242]=_0xb68842;}else _0xb68842=_0xf92fb7;return _0xb68842;}import{registerPendingAgent}from'./async-agent-watcher.js';import{getAllSessions}from'./session.js';import{SUBAGENTS_DIR}from'../paths.js';function generateAgentId(){const _0x310c2e=_0x3c10,_0x1c9d56=_0x3c10;return'alvin-'+_0x437d9c['randomByte'+'s'](-0x8fa+0x2c*0x3b+-0x11e)[_0x310c2e(0x206)](_0x310c2e(0x1fd));}export async function postSubagentExit(_0x377e13,_0x1bceb3){const _0x2a2ba7=_0x3c10,_0x4b30ba=_0x3c10;try{const {getWebPort:_0x5ac8a9,getInternalToken:_0x1ec8bd}=await import(_0x2a2ba7(0x216)+_0x4b30ba(0x1f1)),_0x1314b6=_0x5ac8a9(),_0x340a95=_0x1ec8bd(),_0x296f8e=new AbortController(),_0x244413=setTimeout(()=>_0x296f8e['abort'](),0xe*-0x11b+-0x2115+0x402f);try{await fetch(_0x2a2ba7(0x215)+_0x4b30ba(0x204)+_0x1314b6+(_0x4b30ba(0x1e9)+_0x4b30ba(0x213)+_0x2a2ba7(0x1f0)),{'method':_0x4b30ba(0x212),'headers':{'Content-Type':_0x4b30ba(0x1f2)+_0x2a2ba7(0x20e),'Authorization':'Bearer\x20'+_0x340a95},'body':JSON[_0x4b30ba(0x218)]({'agentId':_0x377e13,'exitCode':_0x1bceb3}),'signal':_0x296f8e[_0x4b30ba(0x20f)]});}finally{clearTimeout(_0x244413);}}catch{}}export function dispatchDetachedAgent(_0x186f8b){const _0x1c2462=_0x3c10,_0x20490d=_0x3c10;try{_0x540009[_0x1c2462(0x1fa)](SUBAGENTS_DIR,{'recursive':!![]});}catch{}const _0x3abaf1=generateAgentId(),_0x53fb33=resolve(SUBAGENTS_DIR,_0x3abaf1+'.jsonl'),_0x16bccc=resolve(SUBAGENTS_DIR,_0x3abaf1+_0x20490d(0x211)),_0x5edb0a=_0x540009['openSync'](_0x53fb33,'w'),_0x19d883=_0x540009[_0x1c2462(0x1ea)](_0x16bccc,'w'),_0xd0cd70={...process['env']};delete _0xd0cd70[_0x1c2462(0x1ef)],delete _0xd0cd70[_0x1c2462(0x1f5)+_0x20490d(0x201)+'NT'];const _0x17efeb=findClaudeBinary();if(!_0x17efeb){_0x540009[_0x1c2462(0x1f9)](_0x5edb0a),_0x540009[_0x1c2462(0x1f9)](_0x19d883);throw new Error('alvin_disp'+_0x1c2462(0x1e8)+_0x1c2462(0x210)+_0x20490d(0x1ed)+'stall\x20clau'+'de-code\x20to'+'\x20enable\x20ba'+_0x1c2462(0x1f6)+'ispatch.');}const _0x43fa45=spawn(_0x17efeb,['-p',_0x186f8b['prompt'],_0x20490d(0x20a)+'ormat',_0x1c2462(0x21a)+'n',_0x1c2462(0x209)],{'cwd':_0x186f8b[_0x1c2462(0x1f3)],'detached':!![],'stdio':[_0x1c2462(0x1ee),_0x5edb0a,_0x19d883],'env':_0xd0cd70});try{_0x540009[_0x20490d(0x1f9)](_0x5edb0a);}catch{}try{_0x540009[_0x20490d(0x1f9)](_0x19d883);}catch{}_0x43fa45['on'](_0x1c2462(0x202),_0x3f0700=>{void postSubagentExit(_0x3abaf1,_0x3f0700);}),_0x43fa45[_0x20490d(0x1ff)](),registerPendingAgent({'agentId':_0x3abaf1,'outputFile':_0x53fb33,'description':_0x186f8b['descriptio'+'n'],'prompt':_0x186f8b[_0x20490d(0x1f7)],'chatId':_0x186f8b['chatId'],'userId':_0x186f8b['userId'],'toolUseId':null,'sessionKey':_0x186f8b[_0x1c2462(0x214)],'platform':_0x186f8b[_0x1c2462(0x1fb)],'pid':_0x43fa45[_0x1c2462(0x20c)]});try{const _0xbef5db=getAllSessions()[_0x20490d(0x208)](_0x186f8b[_0x1c2462(0x214)]);_0xbef5db&&(_0xbef5db['pendingBac'+_0x20490d(0x1f4)+'nt']=(_0xbef5db[_0x1c2462(0x1fc)+_0x1c2462(0x1f4)+'nt']??0x95a+-0x1f52+0x26*0x94)+(-0x84f*-0x3+-0x11*0x242+0xd76));}catch{}return{'agentId':_0x3abaf1,'outputFile':_0x53fb33,'spawned':!![]};}
|
|
@@ -1,104 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v4.13 — Alvin's custom MCP tools, registered with the Claude Agent SDK
|
|
3
|
-
* via `createSdkMcpServer()`.
|
|
4
|
-
*
|
|
5
|
-
* Currently exposes a single tool:
|
|
6
|
-
* `alvin_dispatch_agent(prompt, description)` — spawns a truly
|
|
7
|
-
* detached `claude -p` subprocess that's independent of the parent
|
|
8
|
-
* SDK lifecycle. Claude should prefer this over built-in
|
|
9
|
-
* `Task(run_in_background: true)` for any long-running work on
|
|
10
|
-
* Telegram so the main Telegram session isn't blocked by the SDK's
|
|
11
|
-
* task-notification injection mechanism.
|
|
12
|
-
*
|
|
13
|
-
* The MCP server is created lazily per-query so each query gets fresh
|
|
14
|
-
* handler context (chatId/userId/sessionKey) via a closure.
|
|
15
|
-
*/
|
|
16
|
-
import { createSdkMcpServer, tool, } from "@anthropic-ai/claude-agent-sdk";
|
|
17
|
-
import { z } from "zod";
|
|
18
|
-
import { dispatchDetachedAgent } from "./alvin-dispatch.js";
|
|
19
|
-
/**
|
|
20
|
-
* Build an MCP server bound to a specific turn's context. Pass the
|
|
21
|
-
* returned instance under `mcpServers: { alvin: <instance> }` in the
|
|
22
|
-
* query options.
|
|
23
|
-
*/
|
|
24
|
-
export function buildAlvinMcpServer(ctx) {
|
|
25
|
-
return createSdkMcpServer({
|
|
26
|
-
name: "alvin",
|
|
27
|
-
version: "4.13.0",
|
|
28
|
-
tools: [
|
|
29
|
-
tool("dispatch_agent", [
|
|
30
|
-
"Dispatch a TRULY DETACHED background sub-agent that runs",
|
|
31
|
-
"independently of this session. Use this for ANY long-running",
|
|
32
|
-
"work on Telegram/Slack/Discord/WhatsApp — research tasks,",
|
|
33
|
-
"audits, multi-page scraping, deep analysis — so the main",
|
|
34
|
-
"user session stays responsive and the user can keep chatting",
|
|
35
|
-
"with you while the sub-agent works.",
|
|
36
|
-
"",
|
|
37
|
-
"HOW IT DIFFERS FROM Task(run_in_background: true):",
|
|
38
|
-
"- The built-in Task tool's subprocess is tied to this session,",
|
|
39
|
-
" so aborting the session also kills the sub-agent mid-work.",
|
|
40
|
-
"- `alvin_dispatch.dispatch_agent` spawns a completely",
|
|
41
|
-
" independent `claude -p` subprocess that survives any abort,",
|
|
42
|
-
" crash, or restart of the main bot.",
|
|
43
|
-
"",
|
|
44
|
-
"WHEN TO USE:",
|
|
45
|
-
"- Any audit/research visiting >2 URLs or reading >5 files",
|
|
46
|
-
"- Full-repo scans, code reviews, SEO/security/perf audits",
|
|
47
|
-
"- Anything you'd describe as 'thorough' or 'takes a few min'",
|
|
48
|
-
"",
|
|
49
|
-
"HOW THE RESULT GETS BACK TO THE USER:",
|
|
50
|
-
"- The tool returns { agentId, outputFile } immediately.",
|
|
51
|
-
"- The bot's async-agent watcher polls the outputFile and",
|
|
52
|
-
" delivers the final result as a separate chat message when",
|
|
53
|
-
" the sub-agent completes (success, failure, or 5-min",
|
|
54
|
-
" staleness).",
|
|
55
|
-
"- Your job after calling this tool: tell the user ONE short",
|
|
56
|
-
" sentence about what you dispatched, then END your turn.",
|
|
57
|
-
" Do NOT wait. Do NOT poll the outputFile yourself.",
|
|
58
|
-
].join("\n"), {
|
|
59
|
-
prompt: z
|
|
60
|
-
.string()
|
|
61
|
-
.describe("The full prompt for the sub-agent. Be specific and self-contained — the sub-agent has no access to this conversation's context and will see only this prompt."),
|
|
62
|
-
description: z
|
|
63
|
-
.string()
|
|
64
|
-
.describe("Short human-readable title (e.g. 'SEO audit example.com', 'Research topic X'). Shown to the user when the result arrives."),
|
|
65
|
-
}, async (args) => {
|
|
66
|
-
try {
|
|
67
|
-
const result = dispatchDetachedAgent({
|
|
68
|
-
prompt: args.prompt,
|
|
69
|
-
description: args.description,
|
|
70
|
-
chatId: ctx.chatId,
|
|
71
|
-
userId: ctx.userId,
|
|
72
|
-
sessionKey: ctx.sessionKey,
|
|
73
|
-
platform: ctx.platform,
|
|
74
|
-
cwd: ctx.cwd,
|
|
75
|
-
});
|
|
76
|
-
return {
|
|
77
|
-
content: [
|
|
78
|
-
{
|
|
79
|
-
type: "text",
|
|
80
|
-
text: `✅ Background sub-agent dispatched.\n` +
|
|
81
|
-
`agentId: ${result.agentId}\n` +
|
|
82
|
-
`output_file: ${result.outputFile}\n` +
|
|
83
|
-
`The user will receive the result as a separate message when the sub-agent completes.\n` +
|
|
84
|
-
`End your turn now. Do not wait for the result — it arrives asynchronously.`,
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
91
|
-
return {
|
|
92
|
-
content: [
|
|
93
|
-
{
|
|
94
|
-
type: "text",
|
|
95
|
-
text: `⚠️ Failed to dispatch background agent: ${msg}`,
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
isError: true,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}),
|
|
102
|
-
],
|
|
103
|
-
});
|
|
104
|
-
}
|
|
1
|
+
(function(_0x4817f0,_0x372713){const _0x3a6659=_0x30ba,_0x3a0bb0=_0x30ba,_0x210c0=_0x4817f0();while(!![]){try{const _0x3ca458=parseInt(_0x3a6659(0x1e7))/(-0x49*0x7a+0x1ae9+-0x2*-0x3f1)*(-parseInt(_0x3a6659(0x1fb))/(-0x7e*0x31+-0xe13*0x1+0x2633))+parseInt(_0x3a6659(0x219))/(0x4*0x7a5+0x674+-0x2505)*(parseInt(_0x3a6659(0x242))/(0x166b+-0xeaf*-0x1+0x2*-0x128b))+-parseInt(_0x3a0bb0(0x1e9))/(-0x322+0xeac+-0x3d7*0x3)+-parseInt(_0x3a0bb0(0x249))/(0x2*0x9cb+-0x8da*-0x3+0x2e1e*-0x1)*(parseInt(_0x3a6659(0x1ed))/(0x1097+0x1f*0xd4+-0x2a3c))+parseInt(_0x3a0bb0(0x1dc))/(-0xdb*-0x19+0x8*0x49a+0x1*-0x3a2b)*(-parseInt(_0x3a6659(0x1eb))/(-0x1*-0x1b4e+-0x396*0x9+0x3*0x1ab))+parseInt(_0x3a6659(0x250))/(0x84*-0x21+0xb3f+0x5cf)*(parseInt(_0x3a0bb0(0x26c))/(-0x85*-0x45+0x24e7+0x1*-0x48b5))+parseInt(_0x3a6659(0x231))/(0x124b+-0x1da0+0xb61*0x1);if(_0x3ca458===_0x372713)break;else _0x210c0['push'](_0x210c0['shift']());}catch(_0x52923a){_0x210c0['push'](_0x210c0['shift']());}}}(_0x5f56,-0x131822+-0x16691d*0x1+-0x1e1f*-0x1d6));function _0x30ba(_0x43effb,_0x4f04f1){_0x43effb=_0x43effb-(0x6dc*-0x2+0x7b2*0x1+0xd*0x9b);const _0x206517=_0x5f56();let _0x4b626c=_0x206517[_0x43effb];if(_0x30ba['LjyCBO']===undefined){var _0x3ecb63=function(_0x5b4d0a){const _0x10a937='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4dbe1f='',_0x3798a6='',_0x3464ce=_0x4dbe1f+_0x3ecb63;for(let _0x3927b7=-0x1269*0x2+0xf2*0x11+-0xa6*-0x20,_0x510430,_0x84be93,_0x4948f0=0x1868+-0x237f+0x11*0xa7;_0x84be93=_0x5b4d0a['charAt'](_0x4948f0++);~_0x84be93&&(_0x510430=_0x3927b7%(-0x2020+-0x3*-0xa3f+0x167)?_0x510430*(0x136d*-0x1+0xb3c*0x1+0x871)+_0x84be93:_0x84be93,_0x3927b7++%(0x1*0x363+0x11*-0x1e9+0x1d1a))?_0x4dbe1f+=_0x3464ce['charCodeAt'](_0x4948f0+(0xdaa+0x1d42+-0x2ae2))-(-0x1*0x6e1+-0x3*-0x309+0x118*-0x2)!==-0xf87+-0xc5c+0x1be3?String['fromCharCode'](0x15d4+-0x157c+0xa7&_0x510430>>(-(0x11*-0x131+0x1a12+-0x5cf)*_0x3927b7&-0x1005+-0x23bb+-0x6*-0x8a1)):_0x3927b7:0xe64+0x134f+-0x21b3*0x1){_0x84be93=_0x10a937['indexOf'](_0x84be93);}for(let _0x2ee2ab=0x54a+0x5*0x3cd+0x1*-0x184b,_0x5b5687=_0x4dbe1f['length'];_0x2ee2ab<_0x5b5687;_0x2ee2ab++){_0x3798a6+='%'+('00'+_0x4dbe1f['charCodeAt'](_0x2ee2ab)['toString'](0x1abb+0x3*0x5e5+-0x2c5a))['slice'](-(0x1a6f+0x7b5+-0x2222));}return decodeURIComponent(_0x3798a6);};_0x30ba['uOtLMd']=_0x3ecb63,_0x30ba['pfAdyP']={},_0x30ba['LjyCBO']=!![];}const _0x102bbb=_0x206517[-0xcf1*-0x1+0x1082+-0x1d73],_0x49cafd=_0x43effb+_0x102bbb,_0x5c9ebf=_0x30ba['pfAdyP'][_0x49cafd];if(!_0x5c9ebf){const _0x83b6d1=function(_0x5a2da9){this['HknaiQ']=_0x5a2da9,this['HKuTyL']=[-0x1e8c+0xd*-0x2f9+0x2299*0x2,-0x49*0x7a+0x1ae9+-0x1*-0x7e1,-0x7e*0x31+-0xe13*0x1+0x2631],this['oFRRDS']=function(){return'newState';},this['fgPREF']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['bSYlnT']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x83b6d1['prototype']['zJVKBL']=function(){const _0x36b41a=new RegExp(this['fgPREF']+this['bSYlnT']),_0x1aec1d=_0x36b41a['test'](this['oFRRDS']['toString']())?--this['HKuTyL'][0x4*0x7a5+0x674+-0x2507]:--this['HKuTyL'][0x166b+-0xeaf*-0x1+0x2*-0x128d];return this['lmHdoL'](_0x1aec1d);},_0x83b6d1['prototype']['lmHdoL']=function(_0x3d6a39){if(!Boolean(~_0x3d6a39))return _0x3d6a39;return this['CENBuf'](this['HknaiQ']);},_0x83b6d1['prototype']['CENBuf']=function(_0x440147){for(let _0x4c6de8=-0x322+0xeac+-0x1a6*0x7,_0x1fe0f1=this['HKuTyL']['length'];_0x4c6de8<_0x1fe0f1;_0x4c6de8++){this['HKuTyL']['push'](Math['round'](Math['random']())),_0x1fe0f1=this['HKuTyL']['length'];}return _0x440147(this['HKuTyL'][0x2*0x9cb+-0x8da*-0x3+0x1712*-0x2]);},new _0x83b6d1(_0x30ba)['zJVKBL'](),_0x4b626c=_0x30ba['uOtLMd'](_0x4b626c),_0x30ba['pfAdyP'][_0x49cafd]=_0x4b626c;}else _0x4b626c=_0x5c9ebf;return _0x4b626c;}const _0x34558d=(function(){let _0x525978=!![];return function(_0x4c5281,_0x1261e8){const _0x4d7a43=_0x525978?function(){const _0x1f4ccb=_0x30ba;if(_0x1261e8){const _0x45cf45=_0x1261e8[_0x1f4ccb(0x223)](_0x4c5281,arguments);return _0x1261e8=null,_0x45cf45;}}:function(){};return _0x525978=![],_0x4d7a43;};}()),_0x54c05f=_0x34558d(this,function(){const _0xbe2d41=_0x30ba,_0x56b13c=_0x30ba;return _0x54c05f[_0xbe2d41(0x23f)]()[_0xbe2d41(0x25e)](_0x56b13c(0x246)+'+$')[_0xbe2d41(0x23f)]()[_0x56b13c(0x27a)+'r'](_0x54c05f)[_0x56b13c(0x25e)](_0x56b13c(0x246)+'+$');});_0x54c05f();import{createSdkMcpServer,tool}from'@anthropic-ai/claude-agent-sdk';import{z}from'zod';import{dispatchDetachedAgent}from'./alvin-dispatch.js';function _0x5f56(){const _0x270621=['igf1zgL0CW','ihjLywrPBMCGpG','zgL0igv4yw1WBa','rsbvu0vsoG','BhqGyxmGysbZzq','4PYfiejHy2TNCM91','vgfZAYHYDw5FAq','nc4XmY4W','y2SVrgLZy29Yza','DxjPDhKVCgvYzG','Aw5KzxbLBMrLBG','AxnWyxrJAc5KAq','mKDoD1D3uq','CYbHC3LUyY1HzW','Dc1PBIbuyxnRia','BwLU','CM9TChqGzM9Yia','B250zxH0igfUza','C3bHDgnOx2fNzq','DxjUig5VDY4Gra','ihrOzsb1C2vYia','zgvZy3jPyMu','lsbgDwXSlxjLCa','ihjLC3vSDcbHCW','t05fihnOB3j0','icbeBYbot1qGDW','Dc9YzxnLyxjJAa','CIbYzxn0yxj0ia','v0HftIbutYbvuW','B24GC3rHExmGCG','igfIB3v0ihDOyq','zsb0AguGCMvZDq','igfYCML2zxmGyq','DgX5ig9MihrOAq','CIb0DxjUlG','ChjVBxb0','ihrPDgXLicHLlG','ywX2Aw4','C3nPB24GywXZBW','yxrJAgvKlcb0Aa','ihDPBgWGC2vLia','ifvZzsb0AgLZia','mtyZntzzChjKzw8','CgfYyxrLig1LCW','y3jPyMuGyxmGjW','pJiGvvjmCYbVCG','D29YAYbVBIbuzq','zsbTywLU','BYbUB3qGD2fPDa','ihn1yI1Hz2vUDa','lwfNzw50ihrOyq','AgLZihnLC3nPBW','yxbWBhK','y3jHCgLUzYWGza','lsbbBNKGyxvKAq','y2vZCYWGzMfPBa','quniruqGyMfJAW','CcbJAgf0DgLUzW','CgLJifGNks4GuW','ih0GAw1TzwrPyq','DcbZDxj2AxzLCW','BYbZy2fUCYWGyW','zxnLyxjJAcb0BW','4PQG77IpiezHAwXLzcb0','lsbuAguGyM90jW','zw50ignVBxbSzq','mZK3nJKXmdrHC0Xhtvu','B3jRCY4','BguGyw5K','BMCTCNvUBMLUzW','igeGy29TCgXLDa','Dcb5B3uGzgLZCa','zcbHz2vUDdOG','rKvsuYbguK9nia','B25SEsb0AgLZia','icbPBMrLCgvUza','se9xifrirsbsrq','C2f0Aw9Uj3mGyW','y2HHDeLK','C2vZC2LVBKTLEq','Dg9tDhjPBMC','Aw5NihrOzsbZzq','AM9PBG','nJHpBg1IAg0','lsbuAguGDg9VBa','C2X5lG','zw4Gru5eihLVDq','kcGOlISPkYKRkq','yxvKAxrZlcbTDq','igjHy2TNCM91BG','mJq4ntm4y3LYvNnk','igfUEsbHyM9YDa','DxnLCIbZzxnZAq','ihLVDsDKigrLCW','DgHLihn1yI1HzW','ChjVy2vZCYbPCW','igfMDgvYignHBa','mZbsrMrMAKK','BhqGyxjYAxzLCW','BgvNCMfTl1nSyq','ysbMzxCGBwLUjW','zwnPzMLJigfUza','BgLUzYb0AgLZia','zxnWB25ZAxzLia','nsbMAwXLCW','BIb0AguGCMvZDq','4OcuihjLC2vHCMnO','zxiGy2fUigTLzq','DwiTywDLBNqGDW','BI1YzwfKywjSzq','icbKzwXPDMvYCW','C2vHCMnO','ywDLBNrjzdOG','DgvSEs4','ihzPC2L0Aw5Nia','ywDLBNqGy29TCa','lsbzB3vYigPVyG','igTPBgXZihrOzq','ihjLDhvYBNmGEW','y3DK','BNrGihnWyxDUCW','AxmG4OcuihnVihrO','z3jVDw5Kihn1yG','B3iGj3rHA2vZia','B3v0Chv0rMLSzq','mtKWnJG5neTjzgHZzG','rgLZCgf0y2GGyq','Dg9VBcDZihn1yG','Dgv4Da','B2rLihjLDMLLDW','DxnLCKLK','C3rYAw5N','zw50lIbczsbZCa','igeGC2vWyxjHDa','zgvZy3jPChrPBW','vgHLigz1BgWGCa','BwvZC2fNzq','ywL0lIbeBYbotW','CYbZzxnZAw9UlG','y29UC3rYDwn0BW','igfNzw50swqSia','B2yGDgHLig1HAq','icbJCMfZAcWGBW','ztOG','y2nLC3mGDg8GDa','BYbKAxnWyxrJAa','zM9YiefowsbSBW','l1DOyxrZqxbWia','oe11u0zzra','zs5JB20NlcaNuG','AwXSihjLy2vPDG','zsbVDxrWDxrgAq','zwX5','CYWGu0vpl3nLyW','zw50igbJBgf1za','AgLZignVBNzLCG','ihrHC2TZla','B3v0Chv0x2zPBa','zY4Gj1nftYbHDq','mtm0mZyZoePuENPUDG','C3LUy2HYB25VDq','mtyYmtmZnvjcr3PHCa','u1vmvcbhrvrtia','oda5mJu1n1jmz1LgCa','ihrPzwqGDg8GDa','nZDnEw5lBeq','zsaTCgaGC3vICa'];_0x5f56=function(){return _0x270621;};return _0x5f56();}export function buildAlvinMcpServer(_0x16368e){const _0x2fe877=_0x30ba,_0x5f0fc2=_0x30ba;return createSdkMcpServer({'name':_0x2fe877(0x214),'version':_0x5f0fc2(0x1f6),'tools':[tool('dispatch_a'+'gent',[_0x5f0fc2(0x26d)+'\x20TRULY\x20DET'+_0x2fe877(0x227)+_0x5f0fc2(0x269)+_0x2fe877(0x221)+'t\x20runs',_0x2fe877(0x1f9)+_0x5f0fc2(0x210)+_0x5f0fc2(0x279)+_0x2fe877(0x218)+_0x5f0fc2(0x1da)+_0x5f0fc2(0x234),_0x5f0fc2(0x21d)+_0x2fe877(0x252)+_0x2fe877(0x1f7)+_0x2fe877(0x1db)+_0x2fe877(0x259)+_0x5f0fc2(0x1e4),_0x5f0fc2(0x247)+'lti-page\x20s'+_0x2fe877(0x224)+'eep\x20analys'+_0x5f0fc2(0x268)+_0x5f0fc2(0x21e),_0x5f0fc2(0x24b)+_0x5f0fc2(0x20c)+_0x5f0fc2(0x256)+'and\x20the\x20us'+_0x5f0fc2(0x25a)+_0x5f0fc2(0x228),'with\x20you\x20w'+'hile\x20the\x20s'+_0x2fe877(0x25b)+_0x5f0fc2(0x232),'','HOW\x20IT\x20DIF'+_0x5f0fc2(0x238)+_0x5f0fc2(0x1f5)+'n_backgrou'+'nd:\x20true):','-\x20The\x20buil'+_0x2fe877(0x1fd)+_0x2fe877(0x26e)+_0x2fe877(0x24e)+_0x2fe877(0x1ec)+_0x2fe877(0x222)+'n,','\x20\x20so\x20abort'+_0x2fe877(0x240)+_0x5f0fc2(0x215)+_0x5f0fc2(0x264)+_0x2fe877(0x220)+'\x20mid-work.','-\x20`alvin_d'+_0x2fe877(0x1fa)+_0x2fe877(0x201)+_0x5f0fc2(0x267)+_0x5f0fc2(0x235)+_0x2fe877(0x1e0),_0x5f0fc2(0x23a)+_0x5f0fc2(0x1e2)+_0x2fe877(0x1ee)+'rocess\x20tha'+_0x2fe877(0x22b)+_0x2fe877(0x24a)+',',_0x5f0fc2(0x27d)+_0x5f0fc2(0x20a)+_0x5f0fc2(0x27c)+'n\x20bot.','',_0x5f0fc2(0x20b)+'E:',_0x2fe877(0x225)+_0x2fe877(0x209)+_0x2fe877(0x261)+_0x5f0fc2(0x21c)+_0x2fe877(0x1f0)+_0x5f0fc2(0x257),_0x2fe877(0x205)+_0x5f0fc2(0x22c)+_0x5f0fc2(0x270)+_0x2fe877(0x1e1)+_0x2fe877(0x1f8)+_0x5f0fc2(0x1ef),'-\x20Anything'+_0x5f0fc2(0x24c)+_0x2fe877(0x21b)+'thorough\x27\x20'+_0x2fe877(0x26a)+_0x5f0fc2(0x253),'',_0x5f0fc2(0x23b)+_0x2fe877(0x1ea)+'BACK\x20TO\x20TH'+_0x5f0fc2(0x1f2),_0x2fe877(0x243)+_0x2fe877(0x265)+_0x2fe877(0x27b)+_0x5f0fc2(0x26b)+_0x2fe877(0x22a)+_0x5f0fc2(0x260),_0x5f0fc2(0x22f)+_0x2fe877(0x1fc)+'ent\x20watche'+'r\x20polls\x20th'+_0x5f0fc2(0x1df)+_0x5f0fc2(0x233),_0x5f0fc2(0x25d)+'\x20the\x20final'+_0x5f0fc2(0x206)+_0x5f0fc2(0x274)+'e\x20chat\x20mes'+'sage\x20when','\x20\x20the\x20sub-'+_0x5f0fc2(0x262)+'letes\x20(suc'+_0x5f0fc2(0x226)+'ure,\x20or\x205-'+_0x2fe877(0x1fe),'\x20\x20stalenes'+'s).',_0x2fe877(0x263)+_0x5f0fc2(0x24f)+_0x2fe877(0x255)+'tool:\x20tell'+_0x5f0fc2(0x203)+_0x2fe877(0x207),'\x20\x20sentence'+_0x5f0fc2(0x20d)+_0x2fe877(0x236)+_0x5f0fc2(0x216)+_0x5f0fc2(0x245)+_0x2fe877(0x211),_0x5f0fc2(0x208)+_0x5f0fc2(0x278)+'T\x20poll\x20the'+'\x20outputFil'+'e\x20yourself'+'.'][_0x2fe877(0x241)]('\x0a'),{'prompt':z[_0x5f0fc2(0x272)]()['describe'](_0x2fe877(0x276)+_0x5f0fc2(0x1ff)+_0x5f0fc2(0x24d)+_0x5f0fc2(0x273)+_0x5f0fc2(0x254)+'\x20self-cont'+'ained\x20—\x20th'+'e\x20sub-agen'+'t\x20has\x20no\x20a'+_0x5f0fc2(0x27f)+_0x2fe877(0x1e3)+_0x2fe877(0x23c)+_0x5f0fc2(0x200)+_0x5f0fc2(0x217)+_0x5f0fc2(0x239)+'prompt.'),'description':z[_0x2fe877(0x272)]()[_0x5f0fc2(0x204)]('Short\x20huma'+_0x5f0fc2(0x25c)+_0x5f0fc2(0x213)+_0x5f0fc2(0x1e6)+_0x2fe877(0x1f1)+_0x5f0fc2(0x1dd)+_0x2fe877(0x22d)+_0x2fe877(0x229)+'hown\x20to\x20th'+'e\x20user\x20whe'+_0x5f0fc2(0x258)+_0x2fe877(0x251)+'.')},async _0x22e3d7=>{const _0x56bce9=_0x5f0fc2,_0x41ed8f=_0x2fe877;try{const _0x3b5174=dispatchDetachedAgent({'prompt':_0x22e3d7[_0x56bce9(0x212)],'description':_0x22e3d7[_0x56bce9(0x275)+'n'],'chatId':_0x16368e[_0x41ed8f(0x23d)],'userId':_0x16368e[_0x41ed8f(0x271)],'sessionKey':_0x16368e[_0x41ed8f(0x23e)],'platform':_0x16368e['platform'],'cwd':_0x16368e[_0x41ed8f(0x266)]});return{'content':[{'type':'text','text':_0x41ed8f(0x1f4)+'nd\x20sub-age'+'nt\x20dispatc'+'hed.\x0a'+(_0x56bce9(0x25f)+_0x3b5174['agentId']+'\x0a')+(_0x56bce9(0x1e5)+_0x41ed8f(0x27e)+_0x3b5174['outputFile']+'\x0a')+('The\x20user\x20w'+_0x56bce9(0x1de)+_0x41ed8f(0x20e)+_0x41ed8f(0x1f3)+_0x56bce9(0x21a)+'sage\x20when\x20'+_0x56bce9(0x24d)+_0x41ed8f(0x230)+'tes.\x0a')+('End\x20your\x20t'+_0x41ed8f(0x202)+_0x41ed8f(0x21f)+'\x20for\x20the\x20r'+'esult\x20—\x20it'+_0x41ed8f(0x20f)+_0x41ed8f(0x1e8)+_0x41ed8f(0x244))}]};}catch(_0x40753b){const _0x87ab73=_0x40753b instanceof Error?_0x40753b[_0x41ed8f(0x277)]:String(_0x40753b);return{'content':[{'type':_0x56bce9(0x26f),'text':_0x41ed8f(0x22e)+_0x56bce9(0x1d9)+_0x41ed8f(0x248)+_0x56bce9(0x237)+_0x87ab73}],'isError':!![]};}})]});}
|
|
@@ -1,224 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Asset Index — Scans ~/.alvin-bot/assets/ and builds a searchable registry.
|
|
3
|
-
*
|
|
4
|
-
* Produces:
|
|
5
|
-
* - INDEX.json — machine-readable, used by self-search and skill injection
|
|
6
|
-
* - INDEX.md — human-readable, injected into prompts for asset awareness
|
|
7
|
-
*
|
|
8
|
-
* Scan is filesystem-only (<5ms for ~60 files). No API calls.
|
|
9
|
-
* Re-scans only when ASSETS_DIR has changed since last scan.
|
|
10
|
-
*/
|
|
11
|
-
import fs from "fs";
|
|
12
|
-
import path from "path";
|
|
13
|
-
import { ASSETS_DIR, ASSETS_INDEX_JSON, ASSETS_INDEX_MD } from "../paths.js";
|
|
14
|
-
// ── Cache ───────────────────────────────────────────────
|
|
15
|
-
let cachedIndex = null;
|
|
16
|
-
// ── Helpers ─────────────────────────────────────────────
|
|
17
|
-
/**
|
|
18
|
-
* Walk a directory recursively, yielding file entries.
|
|
19
|
-
*/
|
|
20
|
-
function walkDir(dir) {
|
|
21
|
-
const results = [];
|
|
22
|
-
function walk(currentDir) {
|
|
23
|
-
let entries;
|
|
24
|
-
try {
|
|
25
|
-
entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
for (const entry of entries) {
|
|
31
|
-
const fullPath = path.resolve(currentDir, entry.name);
|
|
32
|
-
if (entry.isDirectory()) {
|
|
33
|
-
walk(fullPath);
|
|
34
|
-
}
|
|
35
|
-
else if (entry.isFile()) {
|
|
36
|
-
// Skip INDEX.json and INDEX.md at ASSETS_DIR root
|
|
37
|
-
if (currentDir === dir && (entry.name === "INDEX.json" || entry.name === "INDEX.md")) {
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
results.push({
|
|
41
|
-
name: entry.name,
|
|
42
|
-
path: fullPath,
|
|
43
|
-
relativePath: path.relative(dir, fullPath),
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
walk(dir);
|
|
49
|
-
return results;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Generate a human-readable description from a filename.
|
|
53
|
-
* "profile-photo.jpeg" → "Profile Photo"
|
|
54
|
-
* "my-document.html" → "My Document"
|
|
55
|
-
*/
|
|
56
|
-
function descriptionFromFilename(filename, category) {
|
|
57
|
-
const name = filename.replace(/\.[^.]+$/, ""); // strip extension
|
|
58
|
-
const words = name.replace(/[-_]/g, " ").trim();
|
|
59
|
-
// Prefix with capitalized category for disambiguation when the filename alone is terse
|
|
60
|
-
const prefix = category ? category.replace(/[-_]/g, " ").replace(/\b\w/g, c => c.toUpperCase()) + ": " : "";
|
|
61
|
-
const title = words.replace(/\b\w/g, c => c.toUpperCase());
|
|
62
|
-
return prefix ? `${prefix}${title}` : title;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Determine category for a file.
|
|
66
|
-
* Files in subdirectories get the directory name as category.
|
|
67
|
-
* Root-level files get a special category based on naming.
|
|
68
|
-
*/
|
|
69
|
-
function categorize(relativePath) {
|
|
70
|
-
const parts = relativePath.split(path.sep);
|
|
71
|
-
if (parts.length > 1) {
|
|
72
|
-
return parts[0]; // directory name
|
|
73
|
-
}
|
|
74
|
-
// Root-level file — categorize by pattern
|
|
75
|
-
const filename = parts[0].toLowerCase();
|
|
76
|
-
if (filename.includes("signature"))
|
|
77
|
-
return "signatures";
|
|
78
|
-
return "misc";
|
|
79
|
-
}
|
|
80
|
-
// ── Public API ──────────────────────────────────────────
|
|
81
|
-
/**
|
|
82
|
-
* Scan ASSETS_DIR and write INDEX.json + INDEX.md.
|
|
83
|
-
* Only re-scans if directory has changed since last scan.
|
|
84
|
-
* Returns the asset index.
|
|
85
|
-
*/
|
|
86
|
-
export function scanAssets() {
|
|
87
|
-
if (!fs.existsSync(ASSETS_DIR)) {
|
|
88
|
-
const empty = { lastScan: new Date().toISOString(), assets: [] };
|
|
89
|
-
cachedIndex = empty;
|
|
90
|
-
return empty;
|
|
91
|
-
}
|
|
92
|
-
// Check if re-scan needed
|
|
93
|
-
if (fs.existsSync(ASSETS_INDEX_JSON)) {
|
|
94
|
-
try {
|
|
95
|
-
const existing = JSON.parse(fs.readFileSync(ASSETS_INDEX_JSON, "utf-8"));
|
|
96
|
-
const dirStat = fs.statSync(ASSETS_DIR);
|
|
97
|
-
const lastScanTime = new Date(existing.lastScan).getTime();
|
|
98
|
-
// Also check subdirectory mtimes (adding a file to a subdir changes subdir mtime, not parent)
|
|
99
|
-
let newestMtime = dirStat.mtimeMs;
|
|
100
|
-
try {
|
|
101
|
-
const subdirs = fs.readdirSync(ASSETS_DIR, { withFileTypes: true });
|
|
102
|
-
for (const d of subdirs) {
|
|
103
|
-
if (d.isDirectory()) {
|
|
104
|
-
const subStat = fs.statSync(path.resolve(ASSETS_DIR, d.name));
|
|
105
|
-
if (subStat.mtimeMs > newestMtime)
|
|
106
|
-
newestMtime = subStat.mtimeMs;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
catch { /* ignore */ }
|
|
111
|
-
if (newestMtime <= lastScanTime) {
|
|
112
|
-
cachedIndex = existing;
|
|
113
|
-
return existing;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// Corrupted index — re-scan
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// Full scan
|
|
121
|
-
const files = walkDir(ASSETS_DIR);
|
|
122
|
-
const assets = [];
|
|
123
|
-
for (const file of files) {
|
|
124
|
-
try {
|
|
125
|
-
const stat = fs.statSync(file.path);
|
|
126
|
-
const category = categorize(file.relativePath);
|
|
127
|
-
assets.push({
|
|
128
|
-
path: file.relativePath,
|
|
129
|
-
absolutePath: file.path,
|
|
130
|
-
category,
|
|
131
|
-
filename: file.name,
|
|
132
|
-
ext: path.extname(file.name),
|
|
133
|
-
size: stat.size,
|
|
134
|
-
modified: new Date(stat.mtimeMs).toISOString(),
|
|
135
|
-
description: descriptionFromFilename(file.name, category),
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
// File disappeared between readdir and stat — skip
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Sort by category then filename
|
|
143
|
-
assets.sort((a, b) => a.category.localeCompare(b.category) || a.filename.localeCompare(b.filename));
|
|
144
|
-
const index = {
|
|
145
|
-
lastScan: new Date().toISOString(),
|
|
146
|
-
assets,
|
|
147
|
-
};
|
|
148
|
-
// Write INDEX.json
|
|
149
|
-
fs.writeFileSync(ASSETS_INDEX_JSON, JSON.stringify(index, null, 2));
|
|
150
|
-
// Write INDEX.md
|
|
151
|
-
const md = generateIndexMd(index);
|
|
152
|
-
fs.writeFileSync(ASSETS_INDEX_MD, md);
|
|
153
|
-
cachedIndex = index;
|
|
154
|
-
return index;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Load asset index from disk (cached after first call).
|
|
158
|
-
*/
|
|
159
|
-
export function loadAssetIndex() {
|
|
160
|
-
if (cachedIndex)
|
|
161
|
-
return cachedIndex;
|
|
162
|
-
if (fs.existsSync(ASSETS_INDEX_JSON)) {
|
|
163
|
-
try {
|
|
164
|
-
cachedIndex = JSON.parse(fs.readFileSync(ASSETS_INDEX_JSON, "utf-8"));
|
|
165
|
-
return cachedIndex;
|
|
166
|
-
}
|
|
167
|
-
catch { /* fall through */ }
|
|
168
|
-
}
|
|
169
|
-
// No index — run scan
|
|
170
|
-
return scanAssets();
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Get INDEX.md content for prompt injection.
|
|
174
|
-
*/
|
|
175
|
-
export function getAssetIndexMd() {
|
|
176
|
-
if (fs.existsSync(ASSETS_INDEX_MD)) {
|
|
177
|
-
return fs.readFileSync(ASSETS_INDEX_MD, "utf-8");
|
|
178
|
-
}
|
|
179
|
-
return "";
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Find assets by category name.
|
|
183
|
-
*/
|
|
184
|
-
export function findAssetsByCategory(category) {
|
|
185
|
-
const index = loadAssetIndex();
|
|
186
|
-
return index.assets.filter(a => a.category === category);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Find assets by keyword match on filename, category, or description.
|
|
190
|
-
*/
|
|
191
|
-
export function findAssetsByKeyword(keywords) {
|
|
192
|
-
const index = loadAssetIndex();
|
|
193
|
-
const lower = keywords.map(k => k.toLowerCase());
|
|
194
|
-
return index.assets.filter(a => lower.some(k => a.filename.toLowerCase().includes(k) ||
|
|
195
|
-
a.category.toLowerCase().includes(k) ||
|
|
196
|
-
a.description.toLowerCase().includes(k)));
|
|
197
|
-
}
|
|
198
|
-
// ── INDEX.md Generator ──────────────────────────────────
|
|
199
|
-
function generateIndexMd(index) {
|
|
200
|
-
const date = new Date().toISOString().slice(0, 10);
|
|
201
|
-
const lines = [`## Your Assets (~/.alvin-bot/assets/) — ${date}\n`];
|
|
202
|
-
// Group by category
|
|
203
|
-
const byCategory = new Map();
|
|
204
|
-
for (const a of index.assets) {
|
|
205
|
-
const list = byCategory.get(a.category) || [];
|
|
206
|
-
list.push(a);
|
|
207
|
-
byCategory.set(a.category, list);
|
|
208
|
-
}
|
|
209
|
-
// Sort categories alphabetically
|
|
210
|
-
const sortedCategories = [...byCategory.keys()].sort();
|
|
211
|
-
for (const cat of sortedCategories) {
|
|
212
|
-
const assets = byCategory.get(cat);
|
|
213
|
-
const names = assets.map(a => a.filename);
|
|
214
|
-
// Compact display: show up to 6 names, then "..."
|
|
215
|
-
const display = names.length > 6
|
|
216
|
-
? names.slice(0, 5).join(", ") + `, ... (+${names.length - 5} more)`
|
|
217
|
-
: names.join(", ");
|
|
218
|
-
lines.push(`- **${cat}/** (${assets.length}): ${display}`);
|
|
219
|
-
}
|
|
220
|
-
const totalSize = index.assets.reduce((sum, a) => sum + a.size, 0);
|
|
221
|
-
const sizeMB = (totalSize / 1_048_576).toFixed(1);
|
|
222
|
-
lines.push(`\nTotal: ${index.assets.length} files, ${sizeMB} MB`);
|
|
223
|
-
return lines.join("\n") + "\n";
|
|
224
|
-
}
|
|
1
|
+
(function(_0x2cc99f,_0x1f1537){const _0x41483f=_0x210c,_0x5551b0=_0x210c,_0x47acf0=_0x2cc99f();while(!![]){try{const _0x150cdb=-parseInt(_0x41483f(0x17c))/(0xa8*0x23+0xfc3+-0x26ba)+parseInt(_0x41483f(0x1a6))/(0xb31+-0x18*0x1d+-0x877)+parseInt(_0x41483f(0x1a5))/(0x157d*-0x1+0x312*0x7+0x2*0x1)+-parseInt(_0x5551b0(0x178))/(-0x2*-0x2bd+0x12e4+-0x185a)+-parseInt(_0x5551b0(0x18a))/(0x18+0x9d7+-0x9ea)*(parseInt(_0x5551b0(0x1a7))/(0x20+-0x2*-0x94b+-0x12b0))+parseInt(_0x5551b0(0x1ae))/(0x6cb*-0x4+-0x44c*0x3+0x2817)+-parseInt(_0x5551b0(0x1a3))/(-0x1*-0x7a4+0x1428+0x6f1*-0x4);if(_0x150cdb===_0x1f1537)break;else _0x47acf0['push'](_0x47acf0['shift']());}catch(_0x163074){_0x47acf0['push'](_0x47acf0['shift']());}}}(_0x1376,0x4fecb*-0x1+0x1459*0x47+0x23bb4));const _0x2b09a7=(function(){let _0x4b12a4=!![];return function(_0x1458ae,_0x367dab){const _0x2e4a1c=_0x4b12a4?function(){const _0x3c0d7c=_0x210c;if(_0x367dab){const _0x688124=_0x367dab[_0x3c0d7c(0x1a4)](_0x1458ae,arguments);return _0x367dab=null,_0x688124;}}:function(){};return _0x4b12a4=![],_0x2e4a1c;};}()),_0x22e2b7=_0x2b09a7(this,function(){const _0x1318b7=_0x210c,_0x2ae547=_0x210c;return _0x22e2b7['toString']()[_0x1318b7(0x1b5)](_0x1318b7(0x19f)+'+$')[_0x2ae547(0x1ab)]()['constructo'+'r'](_0x22e2b7)[_0x2ae547(0x1b5)](_0x2ae547(0x19f)+'+$');});function _0x210c(_0x216854,_0x1f9e4c){_0x216854=_0x216854-(-0x5*0x481+-0xfef+0x27e9);const _0x57cba0=_0x1376();let _0x32d43e=_0x57cba0[_0x216854];if(_0x210c['Sikbuz']===undefined){var _0x942d52=function(_0x4f0186){const _0x1ff0e3='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x21384b='',_0x368c6a='',_0x267382=_0x21384b+_0x942d52;for(let _0x22ae3e=0x1*-0xbff+-0x199e+0x259d,_0x25c254,_0x28bba6,_0x373a5d=-0x18c5+0xa6*-0x1f+0x2cdf;_0x28bba6=_0x4f0186['charAt'](_0x373a5d++);~_0x28bba6&&(_0x25c254=_0x22ae3e%(-0x5fe+0x1*0x1bf+0x443)?_0x25c254*(-0x1*-0x1931+0x976+-0x1*0x2267)+_0x28bba6:_0x28bba6,_0x22ae3e++%(-0x506*0x2+-0x1f34+0x2944))?_0x21384b+=_0x267382['charCodeAt'](_0x373a5d+(-0x14*-0x119+0x1d14+-0x2*0x197f))-(0x2034+0x1361+-0x338b)!==-0x5*-0x6d1+-0x6e*-0x21+-0x3043?String['fromCharCode'](-0xe87+0x24a4+-0x70a*0x3&_0x25c254>>(-(0xeda+-0x11*-0x209+0x3*-0x107b)*_0x22ae3e&0x10a*-0x1c+-0xe5*0x13+0x5*0x939)):_0x22ae3e:0x366+-0x1d4a+0x19e4){_0x28bba6=_0x1ff0e3['indexOf'](_0x28bba6);}for(let _0x10e128=-0x6f1*0x2+-0x1*0x67b+0x1*0x145d,_0x2ea3fb=_0x21384b['length'];_0x10e128<_0x2ea3fb;_0x10e128++){_0x368c6a+='%'+('00'+_0x21384b['charCodeAt'](_0x10e128)['toString'](0x778+-0x41a+-0x34e))['slice'](-(-0xc08*-0x2+-0x1*0x1279+-0x595));}return decodeURIComponent(_0x368c6a);};_0x210c['ekDQsM']=_0x942d52,_0x210c['bCIwmZ']={},_0x210c['Sikbuz']=!![];}const _0x96bb7c=_0x57cba0[0x15d*0xe+0x26e*-0x1+0x10a8*-0x1],_0x1c44c6=_0x216854+_0x96bb7c,_0x5a22b2=_0x210c['bCIwmZ'][_0x1c44c6];if(!_0x5a22b2){const _0x417c84=function(_0x22f49f){this['FXZZTt']=_0x22f49f,this['yzcLwO']=[0x1222+-0x6e9*-0x1+-0x190a,0x633+-0x20d3+0x2*0xd50,-0x1*0x1f0+0x1d82+0x2*-0xdc9],this['bOzFzU']=function(){return'newState';},this['LtrBLw']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['oJmTWE']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x417c84['prototype']['lUoGSW']=function(){const _0x3a5bc6=new RegExp(this['LtrBLw']+this['oJmTWE']),_0x16ab4b=_0x3a5bc6['test'](this['bOzFzU']['toString']())?--this['yzcLwO'][-0x1b*0xbf+-0x1d4d+0x3173]:--this['yzcLwO'][-0x1986+-0xe91+0x137*0x21];return this['tkzwEK'](_0x16ab4b);},_0x417c84['prototype']['tkzwEK']=function(_0xb33088){if(!Boolean(~_0xb33088))return _0xb33088;return this['KiQbyK'](this['FXZZTt']);},_0x417c84['prototype']['KiQbyK']=function(_0x20b960){for(let _0x588cba=0x651*0x1+0x2*0x2c9+0xb3*-0x11,_0x457b90=this['yzcLwO']['length'];_0x588cba<_0x457b90;_0x588cba++){this['yzcLwO']['push'](Math['round'](Math['random']())),_0x457b90=this['yzcLwO']['length'];}return _0x20b960(this['yzcLwO'][0x46*-0xe+0x1*0x11fd+0x7d*-0x1d]);},new _0x417c84(_0x210c)['lUoGSW'](),_0x32d43e=_0x210c['ekDQsM'](_0x32d43e),_0x210c['bCIwmZ'][_0x1c44c6]=_0x32d43e;}else _0x32d43e=_0x5a22b2;return _0x32d43e;}_0x22e2b7();import _0x4d0e8a from'fs';import _0x1924aa from'path';import{ASSETS_DIR,ASSETS_INDEX_JSON,ASSETS_INDEX_MD}from'../paths.js';let cachedIndex=null;function walkDir(_0x46fb85){const _0x2cb87b=[];function _0x52b782(_0x4bef7a){const _0x149fda=_0x210c,_0x55404b=_0x210c;let _0x5ea5e5;try{_0x5ea5e5=_0x4d0e8a[_0x149fda(0x1b4)+'c'](_0x4bef7a,{'withFileTypes':!![]});}catch{return;}for(const _0x56315e of _0x5ea5e5){const _0x53f5b8=_0x1924aa[_0x149fda(0x17b)](_0x4bef7a,_0x56315e['name']);if(_0x56315e[_0x149fda(0x1b1)+'y']())_0x52b782(_0x53f5b8);else{if(_0x56315e['isFile']()){if(_0x4bef7a===_0x46fb85&&(_0x56315e[_0x55404b(0x180)]===_0x149fda(0x1af)||_0x56315e['name']==='INDEX.md'))continue;_0x2cb87b['push']({'name':_0x56315e[_0x55404b(0x180)],'path':_0x53f5b8,'relativePath':_0x1924aa['relative'](_0x46fb85,_0x53f5b8)});}}}}return _0x52b782(_0x46fb85),_0x2cb87b;}function descriptionFromFilename(_0x5c897a,_0x45d19b){const _0x4ea603=_0x210c,_0x6f98ad=_0x210c,_0x381efe=_0x5c897a[_0x4ea603(0x192)](/\.[^.]+$/,''),_0x2373bc=_0x381efe['replace'](/[-_]/g,'\x20')[_0x6f98ad(0x190)](),_0x48aa1e=_0x45d19b?_0x45d19b['replace'](/[-_]/g,'\x20')[_0x6f98ad(0x192)](/\b\w/g,_0x18f4ec=>_0x18f4ec[_0x6f98ad(0x182)+'e']())+':\x20':'',_0x16764b=_0x2373bc['replace'](/\b\w/g,_0x374190=>_0x374190[_0x6f98ad(0x182)+'e']());return _0x48aa1e?''+_0x48aa1e+_0x16764b:_0x16764b;}function categorize(_0x7a0c7d){const _0xf33c43=_0x210c,_0x42e5d1=_0x210c,_0x10de74=_0x7a0c7d[_0xf33c43(0x19e)](_0x1924aa[_0xf33c43(0x197)]);if(_0x10de74['length']>0xa6*-0x1f+-0x1db0+0x31cb)return _0x10de74[0x1*0x1bf+-0x2491+0x1*0x22d2];const _0x1a6e0a=_0x10de74[0x1c05+-0x1*0x545+-0x16c0][_0xf33c43(0x18f)+'e']();if(_0x1a6e0a['includes'](_0x42e5d1(0x195)))return'signatures';return _0xf33c43(0x186);}export function scanAssets(){const _0x512341=_0x210c,_0x2cbccc=_0x210c;if(!_0x4d0e8a['existsSync'](ASSETS_DIR)){const _0x494c0b={'lastScan':new Date()[_0x512341(0x19c)+'g'](),'assets':[]};return cachedIndex=_0x494c0b,_0x494c0b;}if(_0x4d0e8a[_0x512341(0x1a1)](ASSETS_INDEX_JSON))try{const _0x2db0aa=JSON[_0x512341(0x1a8)](_0x4d0e8a[_0x512341(0x1b6)+'nc'](ASSETS_INDEX_JSON,_0x2cbccc(0x1ad))),_0x2a06a7=_0x4d0e8a[_0x512341(0x19b)](ASSETS_DIR),_0x3567c4=new Date(_0x2db0aa[_0x512341(0x175)])[_0x2cbccc(0x19d)]();let _0x453da7=_0x2a06a7[_0x2cbccc(0x184)];try{const _0x1719e5=_0x4d0e8a[_0x512341(0x1b4)+'c'](ASSETS_DIR,{'withFileTypes':!![]});for(const _0xbed867 of _0x1719e5){if(_0xbed867[_0x512341(0x1b1)+'y']()){const _0x464834=_0x4d0e8a[_0x512341(0x19b)](_0x1924aa[_0x2cbccc(0x17b)](ASSETS_DIR,_0xbed867[_0x512341(0x180)]));if(_0x464834['mtimeMs']>_0x453da7)_0x453da7=_0x464834[_0x2cbccc(0x184)];}}}catch{}if(_0x453da7<=_0x3567c4)return cachedIndex=_0x2db0aa,_0x2db0aa;}catch{}const _0x46159a=walkDir(ASSETS_DIR),_0x3251c7=[];for(const _0x19d3f3 of _0x46159a){try{const _0x1108fd=_0x4d0e8a[_0x512341(0x19b)](_0x19d3f3['path']),_0xf6d3b9=categorize(_0x19d3f3['relativePa'+'th']);_0x3251c7['push']({'path':_0x19d3f3['relativePa'+'th'],'absolutePath':_0x19d3f3[_0x512341(0x176)],'category':_0xf6d3b9,'filename':_0x19d3f3[_0x512341(0x180)],'ext':_0x1924aa[_0x512341(0x1aa)](_0x19d3f3[_0x2cbccc(0x180)]),'size':_0x1108fd[_0x512341(0x177)],'modified':new Date(_0x1108fd[_0x2cbccc(0x184)])['toISOStrin'+'g'](),'description':descriptionFromFilename(_0x19d3f3[_0x2cbccc(0x180)],_0xf6d3b9)});}catch{}}_0x3251c7[_0x2cbccc(0x18c)]((_0x108934,_0x1de921)=>_0x108934[_0x2cbccc(0x1b7)][_0x2cbccc(0x17f)+'are'](_0x1de921[_0x2cbccc(0x1b7)])||_0x108934[_0x2cbccc(0x1ac)][_0x512341(0x17f)+'are'](_0x1de921[_0x2cbccc(0x1ac)]));const _0x2d52f5={'lastScan':new Date()['toISOStrin'+'g'](),'assets':_0x3251c7};_0x4d0e8a[_0x2cbccc(0x196)+_0x2cbccc(0x179)](ASSETS_INDEX_JSON,JSON[_0x2cbccc(0x187)](_0x2d52f5,null,-0x1f34+0xb57+0x13df));const _0x53b472=generateIndexMd(_0x2d52f5);return _0x4d0e8a[_0x512341(0x196)+_0x512341(0x179)](ASSETS_INDEX_MD,_0x53b472),cachedIndex=_0x2d52f5,_0x2d52f5;}export function loadAssetIndex(){const _0x453e90=_0x210c,_0x20d545=_0x210c;if(cachedIndex)return cachedIndex;if(_0x4d0e8a[_0x453e90(0x1a1)](ASSETS_INDEX_JSON))try{return cachedIndex=JSON[_0x20d545(0x1a8)](_0x4d0e8a['readFileSy'+'nc'](ASSETS_INDEX_JSON,_0x453e90(0x1ad))),cachedIndex;}catch{}return scanAssets();}export function getAssetIndexMd(){const _0x536d38=_0x210c,_0x376d6c=_0x210c;if(_0x4d0e8a[_0x536d38(0x1a1)](ASSETS_INDEX_MD))return _0x4d0e8a[_0x376d6c(0x1b6)+'nc'](ASSETS_INDEX_MD,_0x376d6c(0x1ad));return'';}export function findAssetsByCategory(_0x28baba){const _0x29a9da=_0x210c,_0x51b514=_0x210c,_0x1aacf4=loadAssetIndex();return _0x1aacf4['assets'][_0x29a9da(0x17d)](_0x59f72b=>_0x59f72b[_0x51b514(0x1b7)]===_0x28baba);}function _0x1376(){const _0x411ce2=['nZq0mty1v2P6y1Du','nJCYnde4thrOB0Xh','nKDHEvbquq','CgfYC2u','z2v0','zxH0BMfTzq','Dg9tDhjPBMC','zMLSzw5HBwu','DxrMltG','mZGWmZuYwvngz1vs','su5ervGUANnVBG','lsaQkG','AxneAxjLy3rVCG','lcaUlI4GkcS','BgvUz3rO','CMvHzgrPCLn5BG','C2vHCMnO','CMvHzezPBgvtEq','y2f0zwDVCNK','BgfZDfnJyw4','Cgf0Aa','C2L6zq','ndK4oti0D0P0zg1y','Ew5J','ktOG','CMvZB2X2zq','mtuZode4DezTz3jx','zMLSDgvY','lYOQicG','Bg9JywXLq29TCa','BMfTzq','Dg9gAxHLza','Dg9vChbLCKnHCW','iYmGww91CIbbCW','BxrPBwvnCW','BhzPBI1IB3qVyq','BwLZyW','C3rYAw5NAwz5','CMvKDwnL','Aw5JBhvKzxm','ntCZmda1wfvAtMn6','BwfW','C29YDa','ie1c','C2v0CYaOFI8Uyq','Dg9mB3DLCKnHCW','DhjPBq','ig1VCMuP','CMvWBgfJzq','ChvZAa','zgvZy3jPChrPBW','C2LNBMf0DxjL','D3jPDgvgAwXLuW','C2vW','cLrVDgfSoIa','AM9PBG','yxnZzxrZ','C3rHDfn5BMm','Dg9ju09tDhjPBG','z2v0vgLTzq','C3bSAxq','kcGOlISPkYKRkq','C2XPy2u','zxHPC3rZu3LUyW','igzPBgvZlca','nduZmda4zLLdwg5e','yxbWBhK'];_0x1376=function(){return _0x411ce2;};return _0x1376();}export function findAssetsByKeyword(_0x4b1eb3){const _0x3f9827=_0x210c,_0xc2b3ed=_0x210c,_0x37653a=loadAssetIndex(),_0x367c1a=_0x4b1eb3['map'](_0x4eec20=>_0x4eec20[_0x3f9827(0x18f)+'e']());return _0x37653a[_0xc2b3ed(0x19a)][_0x3f9827(0x17d)](_0x5f5933=>_0x367c1a['some'](_0x4c7e83=>_0x5f5933[_0x3f9827(0x1ac)][_0x3f9827(0x18f)+'e']()[_0x3f9827(0x189)](_0x4c7e83)||_0x5f5933[_0xc2b3ed(0x1b7)][_0x3f9827(0x18f)+'e']()[_0xc2b3ed(0x189)](_0x4c7e83)||_0x5f5933[_0x3f9827(0x194)+'n'][_0xc2b3ed(0x18f)+'e']()[_0xc2b3ed(0x189)](_0x4c7e83)));}function generateIndexMd(_0x3a837b){const _0x263fa1=_0x210c,_0x6dedbe=_0x210c,_0x43909a=new Date()['toISOStrin'+'g']()['slice'](-0x14*-0x119+0x1d14+-0x8*0x661,0x2034+0x1361+-0x338b),_0x4f40f5=[_0x263fa1(0x183)+_0x263fa1(0x18e)+_0x6dedbe(0x185)+'ssets/)\x20—\x20'+_0x43909a+'\x0a'],_0x2b03e7=new Map();for(const _0x3bcb88 of _0x3a837b[_0x6dedbe(0x19a)]){const _0x330adb=_0x2b03e7['get'](_0x3bcb88[_0x263fa1(0x1b7)])||[];_0x330adb[_0x263fa1(0x193)](_0x3bcb88),_0x2b03e7['set'](_0x3bcb88[_0x263fa1(0x1b7)],_0x330adb);}const _0x45a4af=[..._0x2b03e7['keys']()][_0x263fa1(0x18c)]();for(const _0x3b5f64 of _0x45a4af){const _0x4a4ceb=_0x2b03e7[_0x6dedbe(0x1a9)](_0x3b5f64),_0x216854=_0x4a4ceb[_0x6dedbe(0x18b)](_0x57cba0=>_0x57cba0[_0x6dedbe(0x1ac)]),_0x1f9e4c=_0x216854['length']>-0x5*-0x6d1+-0x6e*-0x21+-0x303d?_0x216854[_0x6dedbe(0x1a0)](-0xe87+0x24a4+-0x275*0x9,0xeda+-0x11*-0x209+0x4a*-0xab)[_0x6dedbe(0x199)](',\x20')+(_0x6dedbe(0x1b2)+(_0x216854['length']-(0x10a*-0x1c+-0xe5*0x13+0xd*0x38c))+_0x263fa1(0x191)):_0x216854[_0x6dedbe(0x199)](',\x20');_0x4f40f5['push'](_0x6dedbe(0x1b0)+_0x3b5f64+_0x6dedbe(0x17e)+_0x4a4ceb[_0x263fa1(0x1b3)]+_0x263fa1(0x17a)+_0x1f9e4c);}const _0x49e346=_0x3a837b[_0x6dedbe(0x19a)][_0x263fa1(0x188)]((_0x32d43e,_0x942d52)=>_0x32d43e+_0x942d52['size'],0x366+-0x1d4a+0x19e4),_0x4dddd0=(_0x49e346/(-0x2758*0x4a+-0x1*0x54f37+0x1*0x20aea7))[_0x263fa1(0x181)](0x778+-0x41a+-0x35d);return _0x4f40f5[_0x263fa1(0x193)](_0x6dedbe(0x198)+_0x3a837b[_0x263fa1(0x19a)][_0x6dedbe(0x1b3)]+_0x6dedbe(0x1a2)+_0x4dddd0+_0x6dedbe(0x18d)),_0x4f40f5['join']('\x0a')+'\x0a';}
|