@melaya/runner 1.0.71 → 1.0.73

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/dist/cli.js CHANGED
@@ -63,8 +63,8 @@ async function main() {
63
63
  // Detect local models
64
64
  const models = await detectModels();
65
65
  if (models.length === 0) {
66
- console.log(chalk.yellow(" ⚠ No local models detected (LM Studio / Ollama not running)"));
67
- console.log(chalk.gray(" Start LM Studio or Ollama, then restart the runner"));
66
+ console.log(chalk.yellow(" ⚠ No local models detected (LM Studio / Ollama not running, Claude Code not logged in)"));
67
+ console.log(chalk.gray(" Start LM Studio or Ollama (or log in to Claude Code), then restart the runner"));
68
68
  }
69
69
  else {
70
70
  for (const m of models) {
package/dist/detect.d.ts CHANGED
@@ -1,8 +1,5 @@
1
- /**
2
- * Auto-detect local LLM providers (LM Studio, Ollama) and list models.
3
- */
4
1
  export interface DetectedModel {
5
- provider: "lmstudio" | "ollama";
2
+ provider: "lmstudio" | "ollama" | "claude_code";
6
3
  name: string;
7
4
  }
8
5
  export declare function detectModels(): Promise<DetectedModel[]>;
package/dist/detect.js CHANGED
@@ -1,6 +1,36 @@
1
1
  /**
2
- * Auto-detect local LLM providers (LM Studio, Ollama) and list models.
2
+ * Auto-detect local LLM providers (LM Studio, Ollama, Claude Code CLI)
3
+ * and list models.
3
4
  */
5
+ import { execFile } from "child_process";
6
+ import { promisify } from "util";
7
+ const execFileAsync = promisify(execFile);
8
+ /** Claude Code is a subscription CLI — when it's installed AND logged in on
9
+ * this machine, report its model aliases so the platform's model picker can
10
+ * show the TRUE availability for local runs (the cloud host's CLI status is
11
+ * the wrong signal: claude_code pipelines execute HERE, on the runner). */
12
+ async function detectClaudeCode() {
13
+ // npm global installs on Windows expose claude.cmd — execFile with a bare
14
+ // name won't resolve .cmd without a shell, so try the .cmd wrapper first.
15
+ const candidates = process.platform === "win32" ? ["claude.cmd", "claude"] : ["claude"];
16
+ for (const exe of candidates) {
17
+ try {
18
+ const { stdout } = await execFileAsync(exe, ["auth", "status"], {
19
+ timeout: 10_000,
20
+ windowsHide: true,
21
+ // .cmd files need a shell on win32; harmless elsewhere.
22
+ shell: process.platform === "win32",
23
+ });
24
+ const status = JSON.parse(stdout);
25
+ if (status.loggedIn) {
26
+ return ["sonnet", "opus", "haiku"].map((name) => ({ provider: "claude_code", name }));
27
+ }
28
+ return []; // installed but logged out — don't advertise models
29
+ }
30
+ catch { /* not installed / not on PATH / non-JSON — try next candidate */ }
31
+ }
32
+ return [];
33
+ }
4
34
  export async function detectModels() {
5
35
  const models = [];
6
36
  // LM Studio — OpenAI-compatible at :1234
@@ -25,5 +55,7 @@ export async function detectModels() {
25
55
  }
26
56
  }
27
57
  catch { /* not running */ }
58
+ // Claude Code CLI — subscription auth on THIS machine
59
+ models.push(...await detectClaudeCode());
28
60
  return models;
29
61
  }
@@ -105,6 +105,48 @@ export function startLocalRelay(socket, verbose, serverUrl) {
105
105
  });
106
106
  return;
107
107
  }
108
+ // ── Mode C RAG search proxy ─────────────────────────────────────
109
+ // A runner-dispatched pipeline's `rag_retrieve` (Mode C: cloud store +
110
+ // local embedder) embeds the query locally then POSTs the vector to
111
+ // `${MEL_BUILDER_URL}/pipelines/<name>/docs/retrieval/search_by_vector`.
112
+ // We forward it over the authenticated socket (the runner is the trust
113
+ // anchor) to `runner:ragSearch`, which calls the server's
114
+ // _forwardSearchByVector → builder search_by_vector on the prod store.
115
+ const sm = req.method === "POST" && req.url
116
+ ? req.url.match(/^\/pipelines\/([^/]+)\/docs\/retrieval\/search_by_vector\/?$/)
117
+ : null;
118
+ if (sm) {
119
+ const pipelineName = decodeURIComponent(sm[1]);
120
+ let sbody = "";
121
+ req.on("data", (chunk) => { sbody += chunk.toString(); });
122
+ req.on("end", () => {
123
+ const replyOnce = (status, body) => {
124
+ if (res.headersSent)
125
+ return;
126
+ res.writeHead(status, { "Content-Type": "application/json" });
127
+ res.end(JSON.stringify(body));
128
+ };
129
+ let parsed;
130
+ try {
131
+ parsed = JSON.parse(sbody || "{}");
132
+ }
133
+ catch {
134
+ replyOnce(400, { results: [], error: "invalid_json" });
135
+ return;
136
+ }
137
+ // Relay timeout < the pipeline's urlopen timeout (30s) so the
138
+ // pipeline always gets a JSON reply rather than its own abort.
139
+ const t = setTimeout(() => replyOnce(504, { results: [], error: "upstream_timeout" }), 25000);
140
+ socket.emit("runner:ragSearch", { name: pipelineName, vector: parsed.vector, limit: parsed.limit }, (resp) => {
141
+ clearTimeout(t);
142
+ if (resp && typeof resp === "object")
143
+ replyOnce(200, resp);
144
+ else
145
+ replyOnce(502, { results: [], error: "no_response" });
146
+ });
147
+ });
148
+ return;
149
+ }
108
150
  if (req.method !== "POST" || req.url !== expectedPath) {
109
151
  res.writeHead(404);
110
152
  res.end("Not found");
package/dist/pythonEnv.js CHANGED
@@ -109,6 +109,14 @@ const PIP_DEPS = [
109
109
  // shared.tools.telegram_user_tools. The bot-API path in
110
110
  // shared.tools.messaging.py uses plain HTTP and needs no extra dep.
111
111
  "telethon",
112
+ // yfinance — TradFi/macro price history + live FX spot for the financial
113
+ // tools (shared.tools.alphavantage_tools yf_* + shared.tools.fx_tools live
114
+ // spot). BOTH modules guard the import (try/except at load + a
115
+ // _require_yfinance() that raises a clear "pip install yfinance" only when a
116
+ // yf_ tool is actually CALLED), so a runner without it still imports every
117
+ // tool module cleanly — this just makes the dep present so the yf_ tools work
118
+ // when attached. Pulls pandas transitively.
119
+ "yfinance",
112
120
  // ── Vector RAG (retrieval mode) ────────────────────────────────────────
113
121
  // ollama — Python client used by agentscope.embedding.OllamaTextEmbedding.
114
122
  // Talks to localhost:11434 (the user's local Ollama daemon) to embed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melaya/runner",
3
- "version": "1.0.71",
3
+ "version": "1.0.73",
4
4
  "description": "Run Melaya AI pipelines locally with your own LM Studio or Ollama models",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,