@roxy-agent/agents 0.1.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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/approvals.js +143 -0
  4. package/dist/approvals.js.map +1 -0
  5. package/dist/classifier.js +436 -0
  6. package/dist/classifier.js.map +1 -0
  7. package/dist/dashboard/client.js +2057 -0
  8. package/dist/dashboard/client.js.map +1 -0
  9. package/dist/dashboard/html.js +57 -0
  10. package/dist/dashboard/html.js.map +1 -0
  11. package/dist/dashboard/icons.js +18 -0
  12. package/dist/dashboard/icons.js.map +1 -0
  13. package/dist/dashboard/server.js +423 -0
  14. package/dist/dashboard/server.js.map +1 -0
  15. package/dist/dashboard/styles.js +1685 -0
  16. package/dist/dashboard/styles.js.map +1 -0
  17. package/dist/dashboard.js +2 -0
  18. package/dist/dashboard.js.map +1 -0
  19. package/dist/db.js +526 -0
  20. package/dist/db.js.map +1 -0
  21. package/dist/index.js +94 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/license.js +257 -0
  24. package/dist/license.js.map +1 -0
  25. package/dist/logger.js +44 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/ml/bash-classifier.js +121 -0
  28. package/dist/ml/bash-classifier.js.map +1 -0
  29. package/dist/ml/embedder.js +79 -0
  30. package/dist/ml/embedder.js.map +1 -0
  31. package/dist/ml/prototypes.js +707 -0
  32. package/dist/ml/prototypes.js.map +1 -0
  33. package/dist/policies.js +289 -0
  34. package/dist/policies.js.map +1 -0
  35. package/dist/slack.js +149 -0
  36. package/dist/slack.js.map +1 -0
  37. package/dist/tools/bash.js +134 -0
  38. package/dist/tools/bash.js.map +1 -0
  39. package/dist/tools/conversation.js +36 -0
  40. package/dist/tools/conversation.js.map +1 -0
  41. package/dist/tools/filesystem.js +243 -0
  42. package/dist/tools/filesystem.js.map +1 -0
  43. package/dist/tools/introspect.js +187 -0
  44. package/dist/tools/introspect.js.map +1 -0
  45. package/dist/tools/network.js +152 -0
  46. package/dist/tools/network.js.map +1 -0
  47. package/dist/tools/policies.js +107 -0
  48. package/dist/tools/policies.js.map +1 -0
  49. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,257 @@
1
+ // Local license + quota module.
2
+ //
3
+ // agent-proxy runs on the user's machine, so credit-gating requires a license
4
+ // file the local server reads + (optionally) a remote API to refresh quota
5
+ // against. This module handles:
6
+ //
7
+ // - the on-disk license file (~/.agent-proxy/license.json)
8
+ // - which tools are billable (vs. introspection / read-only)
9
+ // - per-period usage counters in the SQLite DB
10
+ // - a pre-flight quota check the MCP entrypoint calls before each call
11
+ // - a thin client for the Cloudflare Worker auth + sync endpoints
12
+ //
13
+ // In trial mode (no JWT), the quota is enforced locally only — a determined
14
+ // user can edit the file. That's fine for the funnel; paid features (cloud
15
+ // dashboard, history, team, approvals) live behind the API and aren't
16
+ // reproducible by editing JSON.
17
+ import fs from "node:fs";
18
+ import os from "node:os";
19
+ import path from "node:path";
20
+ import { randomUUID } from "node:crypto";
21
+ import { getUsage, incrementUsage, setUsageSyncedAt } from "./db.js";
22
+ const HOME = os.homedir();
23
+ const CONFIG_DIR = path.join(HOME, ".agent-proxy");
24
+ const LICENSE_PATH = path.join(CONFIG_DIR, "license.json");
25
+ const DEFAULT_QUOTA_FREE = 100;
26
+ const DEFAULT_API_URL = process.env.AGENT_PROXY_API_URL ?? "http://localhost:8787";
27
+ // Tools that count against the user's monthly quota. Read-only / introspection
28
+ // tools are intentionally free so the dashboard + agent self-review never
29
+ // burns credits.
30
+ export const BILLABLE_TOOLS = new Set([
31
+ "bash",
32
+ "filesystem.write",
33
+ "filesystem.delete",
34
+ "network",
35
+ ]);
36
+ // Map raw tool names (as they appear in the MCP server.tool calls) to their
37
+ // billable category. Returns null if the tool isn't billable.
38
+ export function billableCategory(toolName, actionHint) {
39
+ if (toolName === "bash")
40
+ return "bash";
41
+ if (toolName === "fetch_url" || toolName === "network")
42
+ return "network";
43
+ if (toolName === "write_file")
44
+ return "filesystem.write";
45
+ if (toolName === "delete_file")
46
+ return "filesystem.delete";
47
+ // filesystem read/list are free
48
+ if (actionHint && actionHint.startsWith("filesystem.")) {
49
+ return BILLABLE_TOOLS.has(actionHint) ? actionHint : null;
50
+ }
51
+ return null;
52
+ }
53
+ let _cache = null;
54
+ function ensureConfigDir() {
55
+ if (!fs.existsSync(CONFIG_DIR))
56
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
57
+ }
58
+ function nowISO() {
59
+ return new Date().toISOString();
60
+ }
61
+ export function getCurrentPeriod() {
62
+ // YYYY-MM in UTC. Quota resets the 1st of each month.
63
+ const d = new Date();
64
+ return (d.getUTCFullYear() +
65
+ "-" +
66
+ String(d.getUTCMonth() + 1).padStart(2, "0"));
67
+ }
68
+ function defaultLicense() {
69
+ return {
70
+ user_id: "anon_" + randomUUID().slice(0, 12),
71
+ device_id: "dev_" + randomUUID().slice(0, 12),
72
+ email: null,
73
+ plan: "free",
74
+ quota: DEFAULT_QUOTA_FREE,
75
+ api_url: DEFAULT_API_URL,
76
+ jwt: null,
77
+ created_at: nowISO(),
78
+ updated_at: nowISO(),
79
+ };
80
+ }
81
+ export function loadLicense() {
82
+ if (_cache)
83
+ return _cache;
84
+ ensureConfigDir();
85
+ if (!fs.existsSync(LICENSE_PATH)) {
86
+ const fresh = defaultLicense();
87
+ saveLicense(fresh);
88
+ return fresh;
89
+ }
90
+ try {
91
+ const raw = fs.readFileSync(LICENSE_PATH, "utf8");
92
+ const parsed = JSON.parse(raw);
93
+ const merged = { ...defaultLicense(), ...parsed };
94
+ _cache = merged;
95
+ return merged;
96
+ }
97
+ catch {
98
+ const fresh = defaultLicense();
99
+ saveLicense(fresh);
100
+ return fresh;
101
+ }
102
+ }
103
+ export function saveLicense(lic) {
104
+ ensureConfigDir();
105
+ lic.updated_at = nowISO();
106
+ fs.writeFileSync(LICENSE_PATH, JSON.stringify(lic, null, 2), "utf8");
107
+ _cache = lic;
108
+ }
109
+ export function patchLicense(patch) {
110
+ const next = { ...loadLicense(), ...patch };
111
+ saveLicense(next);
112
+ return next;
113
+ }
114
+ export function signOut() {
115
+ const fresh = defaultLicense();
116
+ saveLicense(fresh);
117
+ return fresh;
118
+ }
119
+ export function getQuotaStatus() {
120
+ const lic = loadLicense();
121
+ const period = getCurrentPeriod();
122
+ const used = getUsage(period);
123
+ const remaining = Math.max(0, lic.quota - used);
124
+ return {
125
+ plan: lic.plan,
126
+ quota: lic.quota,
127
+ used,
128
+ remaining,
129
+ period,
130
+ signed_in: !!lic.jwt,
131
+ email: lic.email,
132
+ user_id: lic.user_id,
133
+ };
134
+ }
135
+ // Pre-flight check called by every billable tool. Returns null if the call may
136
+ // proceed, or a QuotaBlock object the tool can return to the agent.
137
+ export function checkQuota(toolName, actionHint) {
138
+ const cat = billableCategory(toolName, actionHint);
139
+ if (!cat)
140
+ return null; // free tool — let it through
141
+ const lic = loadLicense();
142
+ if (lic.plan !== "free")
143
+ return null; // paid plans have no hard cap (yet)
144
+ const status = getQuotaStatus();
145
+ if (status.remaining > 0)
146
+ return null;
147
+ return {
148
+ blocked: true,
149
+ reason: `Free plan limit reached (${status.used}/${status.quota} actions this ${status.period}). ` +
150
+ `Sign in or upgrade at ${upgradeUrl()} — or wait until the next month.`,
151
+ plan: status.plan,
152
+ used: status.used,
153
+ quota: status.quota,
154
+ upgrade_url: upgradeUrl(),
155
+ };
156
+ }
157
+ // Charge one action against the current period. Called after a billable tool
158
+ // successfully reaches the execution stage (whether the classifier allowed,
159
+ // flagged, or denied — every attempt costs one credit, except quota-blocked).
160
+ export function chargeUsage(toolName, actionHint) {
161
+ const cat = billableCategory(toolName, actionHint);
162
+ if (!cat)
163
+ return;
164
+ const lic = loadLicense();
165
+ if (lic.plan !== "free")
166
+ return;
167
+ incrementUsage(getCurrentPeriod());
168
+ }
169
+ export function upgradeUrl() {
170
+ const lic = loadLicense();
171
+ const base = lic.api_url ?? DEFAULT_API_URL;
172
+ return base.replace(/\/$/, "") + "/checkout?user=" + lic.user_id;
173
+ }
174
+ export async function startCloudAuth() {
175
+ const lic = loadLicense();
176
+ if (!lic.api_url)
177
+ return null;
178
+ try {
179
+ const r = await fetch(lic.api_url.replace(/\/$/, "") + "/v1/auth/start", {
180
+ method: "POST",
181
+ headers: { "content-type": "application/json" },
182
+ body: JSON.stringify({
183
+ device_id: lic.device_id,
184
+ user_id: lic.user_id,
185
+ }),
186
+ });
187
+ if (!r.ok)
188
+ return null;
189
+ return (await r.json());
190
+ }
191
+ catch {
192
+ return null;
193
+ }
194
+ }
195
+ export async function pollCloudAuth(code) {
196
+ const lic = loadLicense();
197
+ if (!lic.api_url)
198
+ return null;
199
+ try {
200
+ const r = await fetch(lic.api_url.replace(/\/$/, "") + "/v1/auth/poll", {
201
+ method: "POST",
202
+ headers: { "content-type": "application/json" },
203
+ body: JSON.stringify({ code, device_id: lic.device_id }),
204
+ });
205
+ if (!r.ok)
206
+ return null;
207
+ const data = (await r.json());
208
+ if (data.jwt && data.user_id) {
209
+ patchLicense({
210
+ user_id: data.user_id,
211
+ email: data.email ?? null,
212
+ plan: data.plan ?? "pro",
213
+ quota: data.quota ?? 100_000,
214
+ jwt: data.jwt,
215
+ });
216
+ }
217
+ return data;
218
+ }
219
+ catch {
220
+ return null;
221
+ }
222
+ }
223
+ export async function syncWithCloud() {
224
+ const lic = loadLicense();
225
+ if (!lic.api_url || !lic.jwt)
226
+ return null;
227
+ const period = getCurrentPeriod();
228
+ const used = getUsage(period);
229
+ try {
230
+ const r = await fetch(lic.api_url.replace(/\/$/, "") + "/v1/usage", {
231
+ method: "POST",
232
+ headers: {
233
+ "content-type": "application/json",
234
+ authorization: "Bearer " + lic.jwt,
235
+ },
236
+ body: JSON.stringify({ period, used, device_id: lic.device_id }),
237
+ });
238
+ if (!r.ok)
239
+ return null;
240
+ const data = (await r.json());
241
+ setUsageSyncedAt(period, nowISO());
242
+ if (data.plan && data.quota != null) {
243
+ patchLicense({ plan: data.plan, quota: data.quota });
244
+ }
245
+ return data;
246
+ }
247
+ catch {
248
+ return null;
249
+ }
250
+ }
251
+ export function ensureLicense() {
252
+ return loadLicense();
253
+ }
254
+ export function licensePath() {
255
+ return LICENSE_PATH;
256
+ }
257
+ //# sourceMappingURL=license.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"license.js","sourceRoot":"","sources":["../src/license.ts"],"names":[],"mappings":"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"}
package/dist/logger.js ADDED
@@ -0,0 +1,44 @@
1
+ import { logEvent as dbLogEvent, updateEventResult as dbUpdateEventResult, } from "./db.js";
2
+ // Thin wrapper around the DB layer so call sites have a single, stable
3
+ // surface. We also mirror every event to stderr (stdout is reserved for the
4
+ // MCP stdio transport) so users running the server in a terminal can see
5
+ // activity without opening the dashboard.
6
+ export function logEvent(event) {
7
+ const id = dbLogEvent(event);
8
+ process.stderr.write(formatLine(id, event) + "\n");
9
+ return id;
10
+ }
11
+ export function updateEventResult(id, result, duration_ms, error) {
12
+ dbUpdateEventResult(id, result, duration_ms, error);
13
+ if (error) {
14
+ process.stderr.write(` └─ #${id} ERROR (${duration_ms}ms): ${error}\n`);
15
+ }
16
+ else {
17
+ process.stderr.write(` └─ #${id} ok (${duration_ms}ms)\n`);
18
+ }
19
+ }
20
+ function formatLine(id, e) {
21
+ const tag = e.decision === "denied"
22
+ ? "[DENIED]"
23
+ : e.decision === "flagged"
24
+ ? "[FLAG]"
25
+ : `[${e.risk_level.toUpperCase()}]`;
26
+ const summary = summarizePayload(e.tool, e.action_type, e.payload);
27
+ const reason = e.reason ? ` — ${e.reason}` : "";
28
+ return `${tag} #${id} ${e.tool}.${e.action_type} ${summary}${reason}`;
29
+ }
30
+ function summarizePayload(tool, action, payload) {
31
+ const p = payload;
32
+ if (tool === "bash") {
33
+ const cmd = String(p.command ?? "");
34
+ return cmd.length > 120 ? cmd.slice(0, 117) + "..." : cmd;
35
+ }
36
+ if (tool === "filesystem") {
37
+ return String(p.path ?? "");
38
+ }
39
+ if (tool === "network") {
40
+ return `${String(p.method ?? "GET")} ${String(p.url ?? "")}`;
41
+ }
42
+ return JSON.stringify(payload);
43
+ }
44
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,IAAI,UAAU,EACtB,iBAAiB,IAAI,mBAAmB,GAEzC,MAAM,SAAS,CAAC;AAEjB,uEAAuE;AACvE,4EAA4E;AAC5E,yEAAyE;AACzE,0CAA0C;AAE1C,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,EAAU,EACV,MAAc,EACd,WAAmB,EACnB,KAAc;IAEd,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,WAAW,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,WAAW,OAAO,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAU,EAAE,CAAgB;IAC9C,MAAM,GAAG,GACP,CAAC,CAAC,QAAQ,KAAK,QAAQ;QACrB,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS;YACxB,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG,CAAC;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,OAAO,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,gBAAgB,CACvB,IAAY,EACZ,MAAc,EACd,OAAe;IAEf,MAAM,CAAC,GAAG,OAAkC,CAAC;IAC7C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACpC,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5D,CAAC;IACD,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { embed, cosineSimilarity, isEmbedderReady, loadEmbedder } from "./embedder.js";
2
+ import { BASH_PROTOTYPES } from "./prototypes.js";
3
+ let prototypes = null;
4
+ let prepPromise = null;
5
+ // k for k-NN voting. Each of the top-k nearest prototypes contributes its
6
+ // similarity score to its class; the class with the highest total wins.
7
+ const TOP_K = 5;
8
+ // If the single closest prototype is below this similarity, we don't have a
9
+ // real semantic anchor for the input — defer to the rule-based classifier.
10
+ // Empirically: real wins on natural-language phrasing land at 0.6+; spurious
11
+ // "high" predictions on benign commands sit around 0.3–0.4.
12
+ const MIN_TOP_SIMILARITY = 0.45;
13
+ // When the single closest prototype is this similar, treat it as an
14
+ // effective exact match and trust its class directly. This avoids the k-NN
15
+ // voting from being diluted by many same-tool neighbors of a different
16
+ // class (e.g. `redis-cli FLUSHALL` gets sim=1.00 to its own prototype but
17
+ // 5+ benign `redis-cli GET/SET/...` neighbors would otherwise outvote it).
18
+ const TOP1_TRUST_SIMILARITY = 0.83;
19
+ // Margin-based voting. Only top-K neighbors within VOTING_MARGIN of the
20
+ // top-1 similarity contribute to the class score. Without this, a clear
21
+ // best-match at sim=0.79 can be outvoted by 4 weak same-tool neighbors at
22
+ // sim=0.55 that share the same opposite class — pure k-NN dilution.
23
+ const VOTING_MARGIN = 0.1;
24
+ // Map ML class to (risk_level, decision). Note: ML never returns "denied" —
25
+ // hard-deny is reserved for deterministic regex patterns in classifier.ts.
26
+ const CLASS_TO_CLASSIFICATION = {
27
+ high_flag: { risk_level: "high", decision: "flagged" },
28
+ medium: { risk_level: "medium", decision: "allowed" },
29
+ low: { risk_level: "low", decision: "allowed" },
30
+ };
31
+ export async function prepareBashML() {
32
+ if (prototypes)
33
+ return;
34
+ if (prepPromise)
35
+ return prepPromise;
36
+ prepPromise = (async () => {
37
+ await loadEmbedder();
38
+ const start = Date.now();
39
+ const flat = [];
40
+ for (const cls of Object.keys(BASH_PROTOTYPES)) {
41
+ for (const text of BASH_PROTOTYPES[cls])
42
+ flat.push({ text, cls });
43
+ }
44
+ const built = [];
45
+ for (const { text, cls } of flat) {
46
+ const vec = await embed(text);
47
+ // Copy the typed array — the underlying ONNX buffer can be reused.
48
+ built.push({ text, cls, vec: new Float32Array(vec) });
49
+ }
50
+ prototypes = built;
51
+ process.stderr.write(`[agent-proxy] embedded ${built.length} bash prototypes in ${Date.now() - start}ms\n`);
52
+ })();
53
+ return prepPromise;
54
+ }
55
+ export function isBashMLReady() {
56
+ return isEmbedderReady() && prototypes !== null;
57
+ }
58
+ // Returns null if the model isn't ready yet, or if the prediction is too
59
+ // low-confidence to trust. Caller falls back to rule-based classification in
60
+ // either case.
61
+ export async function classifyBashML(command) {
62
+ if (!prototypes) {
63
+ // Kick off prep in the background so the next call may succeed, but do
64
+ // not block this call.
65
+ void prepareBashML().catch(() => { });
66
+ return null;
67
+ }
68
+ const q = await embed(command);
69
+ // Score every prototype, sort, take top-K, weighted vote by similarity.
70
+ const sims = prototypes.map((p) => ({
71
+ text: p.text,
72
+ cls: p.cls,
73
+ sim: cosineSimilarity(q, p.vec),
74
+ }));
75
+ sims.sort((a, b) => b.sim - a.sim);
76
+ const top = sims.slice(0, TOP_K);
77
+ const best = top[0];
78
+ if (best.sim < MIN_TOP_SIMILARITY)
79
+ return null;
80
+ const scores = {
81
+ high_flag: 0,
82
+ medium: 0,
83
+ low: 0,
84
+ };
85
+ // Only neighbors within VOTING_MARGIN of top-1 vote — see comment above.
86
+ const voteFloor = best.sim - VOTING_MARGIN;
87
+ for (const { cls, sim } of top) {
88
+ if (sim >= voteFloor)
89
+ scores[cls] += sim;
90
+ }
91
+ // Near-exact match short-circuit. When the single closest prototype is
92
+ // very similar, trust its class. Otherwise fall back to top-K voting.
93
+ let predicted;
94
+ let bestScore;
95
+ if (best.sim >= TOP1_TRUST_SIMILARITY) {
96
+ predicted = best.cls;
97
+ bestScore = scores[best.cls];
98
+ }
99
+ else {
100
+ predicted = "low";
101
+ bestScore = -Infinity;
102
+ for (const cls of Object.keys(scores)) {
103
+ if (scores[cls] > bestScore) {
104
+ bestScore = scores[cls];
105
+ predicted = cls;
106
+ }
107
+ }
108
+ }
109
+ const total = scores.high_flag + scores.medium + scores.low;
110
+ const confidence = total > 0 ? bestScore / total : 0;
111
+ const base = CLASS_TO_CLASSIFICATION[predicted];
112
+ return {
113
+ ...base,
114
+ reason: `ml: ~"${best.text}" (sim=${best.sim.toFixed(2)}, conf=${confidence.toFixed(2)})`,
115
+ ml: true,
116
+ top_match: { text: best.text, cls: best.cls, similarity: best.sim },
117
+ scores,
118
+ confidence,
119
+ };
120
+ }
121
+ //# sourceMappingURL=bash-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-classifier.js","sourceRoot":"","sources":["../../src/ml/bash-classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ let embedder = null;
6
+ let loadingPromise = null;
7
+ let loadFailedReason = null;
8
+ const MODEL_NAME = process.env.AGENT_PROXY_ML_MODEL ?? "Xenova/all-MiniLM-L6-v2";
9
+ // Resolve the model cache. Prefer ~/.agent-proxy/models so cached weights
10
+ // survive npm reinstalls and are shared across `npx` runs. If a developer
11
+ // is running from a source checkout that already populated <repo>/data/models,
12
+ // reuse it so we don't re-download a 25MB model on the next launch.
13
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
+ function resolveCacheDir() {
15
+ const env = process.env.AGENT_PROXY_ML_CACHE;
16
+ if (env && env.trim())
17
+ return path.resolve(env.trim());
18
+ const userDir = path.join(os.homedir(), ".agent-proxy", "models");
19
+ const repoLocal = path.resolve(__dirname, "..", "..", "data", "models");
20
+ if (fs.existsSync(repoLocal) && !fs.existsSync(userDir)) {
21
+ return repoLocal;
22
+ }
23
+ return userDir;
24
+ }
25
+ const CACHE_DIR = resolveCacheDir();
26
+ export function isEmbedderReady() {
27
+ return embedder !== null;
28
+ }
29
+ export function embedderLoadError() {
30
+ return loadFailedReason;
31
+ }
32
+ export async function loadEmbedder() {
33
+ if (embedder)
34
+ return embedder;
35
+ if (loadingPromise)
36
+ return loadingPromise;
37
+ loadingPromise = (async () => {
38
+ const start = Date.now();
39
+ process.stderr.write(`[agent-proxy] loading ML embedder ${MODEL_NAME} (cache=${CACHE_DIR})…\n`);
40
+ try {
41
+ const tx = await import("@huggingface/transformers");
42
+ // Cache directory and offline-friendly behavior.
43
+ tx.env.cacheDir = CACHE_DIR;
44
+ tx.env.allowLocalModels = true;
45
+ const pipe = (await tx.pipeline("feature-extraction", MODEL_NAME, {
46
+ // Quantized ONNX (~25 MB) — perfectly accurate enough for short
47
+ // command snippets and ~3-5x faster on CPU.
48
+ dtype: "q8",
49
+ }));
50
+ embedder = pipe;
51
+ const elapsed = Date.now() - start;
52
+ process.stderr.write(`[agent-proxy] embedder ready in ${elapsed}ms\n`);
53
+ return pipe;
54
+ }
55
+ catch (err) {
56
+ const e = err;
57
+ loadFailedReason = e.message;
58
+ process.stderr.write(`[agent-proxy] embedder load FAILED: ${e.message} — falling back to rules-only classifier\n`);
59
+ throw err;
60
+ }
61
+ })();
62
+ return loadingPromise;
63
+ }
64
+ // Embed a string and return its (mean-pooled, L2-normalized) vector.
65
+ export async function embed(text) {
66
+ const ext = await loadEmbedder();
67
+ const out = await ext(text, { pooling: "mean", normalize: true });
68
+ return out.data;
69
+ }
70
+ // Cosine similarity. Inputs are expected to already be L2-normalized, so this
71
+ // reduces to a plain dot product.
72
+ export function cosineSimilarity(a, b) {
73
+ let s = 0;
74
+ const len = Math.min(a.length, b.length);
75
+ for (let i = 0; i < len; i++)
76
+ s += a[i] * b[i];
77
+ return s;
78
+ }
79
+ //# sourceMappingURL=embedder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedder.js","sourceRoot":"","sources":["../../src/ml/embedder.ts"],"names":[],"mappings":"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"}