autohand-cli 0.7.3 → 0.7.4

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/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  import "./chunk-QHPFA6OE.js";
25
25
  import {
26
26
  metadata as metadata25
27
- } from "./chunk-ZYHQ652D.js";
27
+ } from "./chunk-C2NFLFHH.js";
28
28
  import {
29
29
  metadata as metadata26
30
30
  } from "./chunk-CXZEPTRI.js";
@@ -41,13 +41,13 @@ import {
41
41
  import {
42
42
  metadata as metadata18,
43
43
  package_default
44
- } from "./chunk-KNYGI365.js";
44
+ } from "./chunk-546JQ3ND.js";
45
45
  import {
46
46
  metadata as metadata19
47
- } from "./chunk-6XITU2RU.js";
47
+ } from "./chunk-2FSQPRPJ.js";
48
48
  import {
49
49
  metadata as metadata20
50
- } from "./chunk-52HPEJ4P.js";
50
+ } from "./chunk-6LP2GO5C.js";
51
51
  import {
52
52
  getAuthClient
53
53
  } from "./chunk-CHQMK2ZG.js";
@@ -59,7 +59,7 @@ import {
59
59
  loadConfig,
60
60
  resolveWorkspaceRoot,
61
61
  saveConfig
62
- } from "./chunk-B2BPL6IL.js";
62
+ } from "./chunk-PVM5I5WI.js";
63
63
  import {
64
64
  metadata as metadata21
65
65
  } from "./chunk-YDH2BMEN.js";
@@ -1988,6 +1988,128 @@ var OpenRouterProvider = class {
1988
1988
  }
1989
1989
  };
1990
1990
 
1991
+ // src/utils/platform.ts
1992
+ function isAppleSilicon() {
1993
+ return process.platform === "darwin" && process.arch === "arm64";
1994
+ }
1995
+ function isMLXSupported() {
1996
+ return isAppleSilicon();
1997
+ }
1998
+
1999
+ // src/providers/MLXProvider.ts
2000
+ var MLXProvider = class {
2001
+ constructor(config) {
2002
+ const port = config.port || 8080;
2003
+ this.baseUrl = config.baseUrl || `http://localhost:${port}`;
2004
+ this.model = config.model || "mlx-model";
2005
+ }
2006
+ getName() {
2007
+ return "mlx";
2008
+ }
2009
+ setModel(model) {
2010
+ this.model = model;
2011
+ }
2012
+ async listModels() {
2013
+ if (!isMLXSupported()) {
2014
+ return [];
2015
+ }
2016
+ try {
2017
+ const response = await fetch(`${this.baseUrl}/v1/models`);
2018
+ if (!response.ok) {
2019
+ return this.model ? [this.model] : [];
2020
+ }
2021
+ const data = await response.json();
2022
+ return data.data?.map((m) => m.id) ?? (this.model ? [this.model] : []);
2023
+ } catch {
2024
+ return this.model ? [this.model] : [];
2025
+ }
2026
+ }
2027
+ async isAvailable() {
2028
+ if (!isMLXSupported()) {
2029
+ return false;
2030
+ }
2031
+ try {
2032
+ const response = await fetch(`${this.baseUrl}/v1/models`);
2033
+ return response.ok;
2034
+ } catch {
2035
+ return false;
2036
+ }
2037
+ }
2038
+ async complete(request) {
2039
+ if (!isMLXSupported()) {
2040
+ throw new Error("MLX is only supported on macOS with Apple Silicon");
2041
+ }
2042
+ const body = {
2043
+ model: request.model || this.model,
2044
+ messages: request.messages.map((msg) => {
2045
+ const mapped = {
2046
+ role: msg.role,
2047
+ content: msg.content
2048
+ };
2049
+ if (msg.name) mapped.name = msg.name;
2050
+ if (msg.role === "tool" && msg.tool_call_id) mapped.tool_call_id = msg.tool_call_id;
2051
+ if (msg.role === "assistant" && msg.tool_calls) mapped.tool_calls = msg.tool_calls;
2052
+ return mapped;
2053
+ }),
2054
+ temperature: request.temperature ?? 0.7,
2055
+ max_tokens: request.maxTokens ?? 4096,
2056
+ stream: false
2057
+ };
2058
+ if (request.tools && request.tools.length > 0) {
2059
+ body.tools = request.tools.map((tool) => ({
2060
+ type: "function",
2061
+ function: {
2062
+ name: tool.name,
2063
+ description: tool.description,
2064
+ parameters: tool.parameters ?? { type: "object", properties: {} }
2065
+ }
2066
+ }));
2067
+ }
2068
+ const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
2069
+ method: "POST",
2070
+ headers: {
2071
+ "Content-Type": "application/json"
2072
+ },
2073
+ body: JSON.stringify(body),
2074
+ signal: request.signal
2075
+ });
2076
+ if (!response.ok) {
2077
+ throw new Error(`MLX API error: ${response.status} ${response.statusText}`);
2078
+ }
2079
+ const data = await response.json();
2080
+ const choice = data.choices[0];
2081
+ let toolCalls;
2082
+ if (choice?.message.tool_calls?.length) {
2083
+ toolCalls = choice.message.tool_calls.map((tc) => ({
2084
+ id: tc.id,
2085
+ type: "function",
2086
+ function: {
2087
+ name: tc.function.name,
2088
+ arguments: tc.function.arguments
2089
+ }
2090
+ }));
2091
+ }
2092
+ let usage;
2093
+ if (data.usage) {
2094
+ usage = {
2095
+ promptTokens: data.usage.prompt_tokens,
2096
+ completionTokens: data.usage.completion_tokens,
2097
+ totalTokens: data.usage.total_tokens
2098
+ };
2099
+ }
2100
+ const finishReason = toolCalls?.length ? "tool_calls" : choice?.finish_reason === "stop" || choice?.finish_reason === "length" || choice?.finish_reason === "content_filter" ? choice.finish_reason : "stop";
2101
+ return {
2102
+ id: data.id || `mlx-${Date.now()}`,
2103
+ created: data.created || Math.floor(Date.now() / 1e3),
2104
+ content: choice?.message.content ?? "",
2105
+ toolCalls,
2106
+ finishReason,
2107
+ usage,
2108
+ raw: data
2109
+ };
2110
+ }
2111
+ };
2112
+
1991
2113
  // src/providers/ProviderFactory.ts
1992
2114
  var ProviderNotConfiguredError = class extends Error {
1993
2115
  constructor(providerName) {
@@ -2039,6 +2161,11 @@ var ProviderFactory = class {
2039
2161
  return new UnconfiguredProvider("llamacpp");
2040
2162
  }
2041
2163
  return new LlamaCppProvider(config.llamacpp);
2164
+ case "mlx":
2165
+ if (!config.mlx) {
2166
+ return new UnconfiguredProvider("mlx");
2167
+ }
2168
+ return new MLXProvider(config.mlx);
2042
2169
  case "openrouter":
2043
2170
  default:
2044
2171
  if (!config.openrouter) {
@@ -2048,16 +2175,24 @@ var ProviderFactory = class {
2048
2175
  }
2049
2176
  }
2050
2177
  /**
2051
- * Get all available provider names
2178
+ * Get all available provider names.
2179
+ * MLX is only included on Apple Silicon (macOS + arm64).
2052
2180
  */
2053
2181
  static getProviderNames() {
2054
- return ["openrouter", "ollama", "openai", "llamacpp"];
2182
+ const providers = ["openrouter", "ollama", "openai", "llamacpp"];
2183
+ if (isMLXSupported()) {
2184
+ providers.push("mlx");
2185
+ }
2186
+ return providers;
2055
2187
  }
2056
2188
  /**
2057
- * Check if a provider name is valid
2189
+ * Check if a provider name is valid.
2190
+ * Note: This checks if the name is a valid provider type, not if it's available on this platform.
2191
+ * MLX is always a valid provider name, but may not be available on non-Apple Silicon systems.
2058
2192
  */
2059
2193
  static isValidProvider(name) {
2060
- return this.getProviderNames().includes(name);
2194
+ const allProviders = ["openrouter", "ollama", "openai", "llamacpp", "mlx"];
2195
+ return allProviders.includes(name);
2061
2196
  }
2062
2197
  };
2063
2198
 
@@ -8458,15 +8593,15 @@ var SlashCommandHandler = class {
8458
8593
  return null;
8459
8594
  }
8460
8595
  case "/status": {
8461
- const { status } = await import("./status-ROTJZEKU.js");
8596
+ const { status } = await import("./status-UT4UQN3H.js");
8462
8597
  return status(this.ctx);
8463
8598
  }
8464
8599
  case "/login": {
8465
- const { login } = await import("./login-BZ7J4Z4M.js");
8600
+ const { login } = await import("./login-NYWZRZO5.js");
8466
8601
  return login({ config: this.ctx.config });
8467
8602
  }
8468
8603
  case "/logout": {
8469
- const { logout } = await import("./logout-BZKEMNHB.js");
8604
+ const { logout } = await import("./logout-MBS7L3ZW.js");
8470
8605
  return logout({ config: this.ctx.config });
8471
8606
  }
8472
8607
  case "/permissions": {
@@ -8514,7 +8649,7 @@ var SlashCommandHandler = class {
8514
8649
  });
8515
8650
  }
8516
8651
  case "/theme": {
8517
- const { theme } = await import("./theme-JAMJSCKR.js");
8652
+ const { theme } = await import("./theme-CY7WF4M6.js");
8518
8653
  if (!this.ctx.config) {
8519
8654
  console.log(chalk8.yellow("Config not available for theme selection."));
8520
8655
  return null;
@@ -9203,8 +9338,7 @@ var DEFAULT_CONFIG = {
9203
9338
  timeout: 5e3,
9204
9339
  maxRetries: 3,
9205
9340
  offlineQueue: true,
9206
- cliVersion: "0.1.0",
9207
- companySecret: ""
9341
+ cliVersion: package_default.version
9208
9342
  };
9209
9343
  var FeedbackApiClient = class {
9210
9344
  constructor(configOverrides) {
@@ -9280,18 +9414,18 @@ var FeedbackApiClient = class {
9280
9414
  }
9281
9415
  /**
9282
9416
  * Send feedback to API endpoint
9417
+ * No authentication required - endpoint is rate-limited instead
9283
9418
  */
9284
9419
  async sendToApi(submission) {
9285
9420
  const controller = new AbortController();
9286
9421
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
9287
- const authToken = `${submission.deviceId}.${this.config.companySecret}`;
9288
9422
  try {
9289
9423
  const response = await fetch(`${this.config.baseUrl}/v1/feedback`, {
9290
9424
  method: "POST",
9291
9425
  headers: {
9292
9426
  "Content-Type": "application/json",
9293
- "Authorization": `Bearer ${authToken}`,
9294
- "X-CLI-Version": this.config.cliVersion
9427
+ "X-CLI-Version": this.config.cliVersion,
9428
+ "X-Device-ID": submission.deviceId
9295
9429
  },
9296
9430
  body: JSON.stringify(submission),
9297
9431
  signal: controller.signal
@@ -12161,7 +12295,10 @@ var AutohandAgent = class {
12161
12295
  }
12162
12296
  });
12163
12297
  this.errorLogger = new ErrorLogger(package_default.version);
12164
- this.feedbackManager = new FeedbackManager();
12298
+ this.feedbackManager = new FeedbackManager({
12299
+ apiBaseUrl: runtime.config.api?.baseUrl || "https://api.autohand.ai",
12300
+ cliVersion: package_default.version
12301
+ });
12165
12302
  this.skillsRegistry = new SkillsRegistry(AUTOHAND_PATHS.skills);
12166
12303
  this.telemetryManager = new TelemetryManager({
12167
12304
  enabled: runtime.config.telemetry?.enabled === true,
@@ -12785,14 +12922,15 @@ If lint or tests fail, report the issues but do NOT commit.`;
12785
12922
  }
12786
12923
  async promptModelSelection() {
12787
12924
  try {
12788
- const allProviders = ["openrouter", "ollama", "llamacpp", "openai"];
12925
+ const allProviders = ProviderFactory.getProviderNames();
12789
12926
  const providerChoices = allProviders.map((name) => {
12790
12927
  const isConfigured = this.isProviderConfigured(name);
12791
12928
  const indicator = isConfigured ? chalk14.green("\u25CF") : chalk14.red("\u25CB");
12792
12929
  const current = name === this.activeProvider ? chalk14.cyan(" (current)") : "";
12930
+ const siliconNote = name === "mlx" ? chalk14.gray(" (Apple Silicon)") : "";
12793
12931
  return {
12794
12932
  name,
12795
- message: `${indicator} ${name}${current}`,
12933
+ message: `${indicator} ${name}${current}${siliconNote}`,
12796
12934
  value: name
12797
12935
  };
12798
12936
  });
@@ -12843,6 +12981,9 @@ ${selectedProvider} is not configured yet. Let's set it up!
12843
12981
  case "openai":
12844
12982
  await this.configureOpenAI();
12845
12983
  break;
12984
+ case "mlx":
12985
+ await this.configureMLX();
12986
+ break;
12846
12987
  }
12847
12988
  }
12848
12989
  async configureOpenRouter() {
@@ -13012,6 +13153,59 @@ ${selectedProvider} is not configured yet. Let's set it up!
13012
13153
  throw error;
13013
13154
  }
13014
13155
  }
13156
+ async configureMLX() {
13157
+ try {
13158
+ console.log(chalk14.cyan("MLX Configuration (Apple Silicon)"));
13159
+ console.log(chalk14.gray("MLX provides local LLM inference optimized for Apple Silicon."));
13160
+ console.log(chalk14.gray("Make sure mlx-lm server is running: mlx_lm.server --model <model-name>\n"));
13161
+ const mlxUrl = "http://localhost:8080";
13162
+ let availableModels = [];
13163
+ try {
13164
+ const response = await fetch(`${mlxUrl}/v1/models`);
13165
+ if (response.ok) {
13166
+ const data = await response.json();
13167
+ availableModels = data.data?.map((m) => m.id) || [];
13168
+ }
13169
+ } catch {
13170
+ console.log(chalk14.yellow("\u26A0 Could not connect to MLX server. Make sure it's running.\n"));
13171
+ }
13172
+ let modelAnswer;
13173
+ if (availableModels.length > 0) {
13174
+ modelAnswer = await enquirer3.prompt([
13175
+ {
13176
+ type: "select",
13177
+ name: "model",
13178
+ message: "Select a model",
13179
+ choices: availableModels
13180
+ }
13181
+ ]);
13182
+ } else {
13183
+ modelAnswer = await enquirer3.prompt([
13184
+ {
13185
+ type: "input",
13186
+ name: "model",
13187
+ message: "Enter model name (e.g., mlx-community/Llama-3.2-3B-Instruct-4bit)",
13188
+ initial: "mlx-community/Llama-3.2-3B-Instruct-4bit"
13189
+ }
13190
+ ]);
13191
+ }
13192
+ this.runtime.config.mlx = {
13193
+ baseUrl: mlxUrl,
13194
+ model: modelAnswer.model
13195
+ };
13196
+ this.runtime.config.provider = "mlx";
13197
+ this.runtime.options.model = modelAnswer.model;
13198
+ await saveConfig(this.runtime.config);
13199
+ this.resetLlmClient("mlx", modelAnswer.model);
13200
+ console.log(chalk14.green("\n\u2713 MLX configured successfully!"));
13201
+ } catch (error) {
13202
+ if (error.name === "ExitPromptError" || error.message?.includes("canceled")) {
13203
+ console.log(chalk14.gray("\nConfiguration cancelled."));
13204
+ return;
13205
+ }
13206
+ throw error;
13207
+ }
13208
+ }
13015
13209
  async changeProviderModel(provider) {
13016
13210
  try {
13017
13211
  const currentSettings = getProviderConfig(this.runtime.config, provider);
@@ -15102,6 +15296,7 @@ ${chalk14.gray("\u203A")} ${inputPreview}${chalk14.gray("\u258B")}`;
15102
15296
  if (this.runtime.config.ollama) providers.push("ollama");
15103
15297
  if (this.runtime.config.llamacpp) providers.push("llamacpp");
15104
15298
  if (this.runtime.config.openai) providers.push("openai");
15299
+ if (this.runtime.config.mlx) providers.push("mlx");
15105
15300
  return providers.length ? providers : ["openrouter"];
15106
15301
  }
15107
15302
  setProviderModel(provider, model) {
@@ -15109,7 +15304,8 @@ ${chalk14.gray("\u203A")} ${inputPreview}${chalk14.gray("\u258B")}`;
15109
15304
  openrouter: this.runtime.config.openrouter ?? (this.runtime.config.openrouter = { apiKey: "", model }),
15110
15305
  ollama: this.runtime.config.ollama ?? (this.runtime.config.ollama = { model }),
15111
15306
  llamacpp: this.runtime.config.llamacpp ?? (this.runtime.config.llamacpp = { model }),
15112
- openai: this.runtime.config.openai ?? (this.runtime.config.openai = { model })
15307
+ openai: this.runtime.config.openai ?? (this.runtime.config.openai = { model }),
15308
+ mlx: this.runtime.config.mlx ?? (this.runtime.config.mlx = { model })
15113
15309
  };
15114
15310
  cfgMap[provider].model = model;
15115
15311
  this.activeProvider = provider;
@@ -17308,7 +17504,7 @@ async function handleSingleRequest(request, adapter) {
17308
17504
  process.title = "autohand";
17309
17505
  function getGitCommit() {
17310
17506
  if (true) {
17311
- return "f92e70a";
17507
+ return "5392e8c";
17312
17508
  }
17313
17509
  try {
17314
17510
  return execSync3("git rev-parse --short HEAD", { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }).trim();
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  login,
3
3
  metadata
4
- } from "./chunk-6XITU2RU.js";
4
+ } from "./chunk-2FSQPRPJ.js";
5
5
  import "./chunk-CHQMK2ZG.js";
6
- import "./chunk-B2BPL6IL.js";
6
+ import "./chunk-PVM5I5WI.js";
7
7
  import "./chunk-7BYSXAKS.js";
8
8
  import "./chunk-FUEL6BK7.js";
9
9
  export {
@@ -1,12 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
3
 
4
- var _chunkFEI2GPAWcjs = require('./chunk-FEI2GPAW.cjs');
4
+ var _chunk2E2COWKBcjs = require('./chunk-2E2COWKB.cjs');
5
5
  require('./chunk-REPKBECD.cjs');
6
- require('./chunk-SXUZ3CX3.cjs');
6
+ require('./chunk-QMVTT55Y.cjs');
7
7
  require('./chunk-3HPUOQJN.cjs');
8
8
  require('./chunk-XTHHDIBG.cjs');
9
9
 
10
10
 
11
11
 
12
- exports.login = _chunkFEI2GPAWcjs.login; exports.metadata = _chunkFEI2GPAWcjs.metadata;
12
+ exports.login = _chunk2E2COWKBcjs.login; exports.metadata = _chunk2E2COWKBcjs.metadata;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  logout,
3
3
  metadata
4
- } from "./chunk-52HPEJ4P.js";
4
+ } from "./chunk-6LP2GO5C.js";
5
5
  import "./chunk-CHQMK2ZG.js";
6
- import "./chunk-B2BPL6IL.js";
6
+ import "./chunk-PVM5I5WI.js";
7
7
  import "./chunk-7BYSXAKS.js";
8
8
  import "./chunk-FUEL6BK7.js";
9
9
  export {
@@ -0,0 +1,12 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunk536VWSZKcjs = require('./chunk-536VWSZK.cjs');
5
+ require('./chunk-REPKBECD.cjs');
6
+ require('./chunk-QMVTT55Y.cjs');
7
+ require('./chunk-3HPUOQJN.cjs');
8
+ require('./chunk-XTHHDIBG.cjs');
9
+
10
+
11
+
12
+ exports.logout = _chunk536VWSZKcjs.logout; exports.metadata = _chunk536VWSZKcjs.metadata;
@@ -0,0 +1,8 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunkXJZYEURAcjs = require('./chunk-XJZYEURA.cjs');
5
+
6
+
7
+
8
+ exports.metadata = _chunkXJZYEURAcjs.metadata; exports.status = _chunkXJZYEURAcjs.status;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  metadata,
3
3
  status
4
- } from "./chunk-KNYGI365.js";
4
+ } from "./chunk-546JQ3ND.js";
5
5
  export {
6
6
  metadata,
7
7
  status
@@ -0,0 +1,12 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+ var _chunkHYTYXN2Gcjs = require('./chunk-HYTYXN2G.cjs');
6
+ require('./chunk-QMVTT55Y.cjs');
7
+ require('./chunk-XTHHDIBG.cjs');
8
+
9
+
10
+
11
+
12
+ exports.metadata = _chunkHYTYXN2Gcjs.metadata; exports.theme = _chunkHYTYXN2Gcjs.theme; exports.themeInfo = _chunkHYTYXN2Gcjs.themeInfo;
@@ -2,8 +2,8 @@ import {
2
2
  metadata,
3
3
  theme,
4
4
  themeInfo
5
- } from "./chunk-ZYHQ652D.js";
6
- import "./chunk-B2BPL6IL.js";
5
+ } from "./chunk-C2NFLFHH.js";
6
+ import "./chunk-PVM5I5WI.js";
7
7
  import "./chunk-FUEL6BK7.js";
8
8
  export {
9
9
  metadata,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autohand-cli",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "licenses": "SEE LICENSE IN LICENSE",
5
5
  "description": "Autohand interactive coding agent CLI powered by LLMs.",
6
6
  "repository": {
@@ -1,12 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
- var _chunkU43RFUBRcjs = require('./chunk-U43RFUBR.cjs');
5
- require('./chunk-REPKBECD.cjs');
6
- require('./chunk-SXUZ3CX3.cjs');
7
- require('./chunk-3HPUOQJN.cjs');
8
- require('./chunk-XTHHDIBG.cjs');
9
-
10
-
11
-
12
- exports.logout = _chunkU43RFUBRcjs.logout; exports.metadata = _chunkU43RFUBRcjs.metadata;
@@ -1,8 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
- var _chunk7EIL6P6Qcjs = require('./chunk-7EIL6P6Q.cjs');
5
-
6
-
7
-
8
- exports.metadata = _chunk7EIL6P6Qcjs.metadata; exports.status = _chunk7EIL6P6Qcjs.status;
@@ -1,12 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
-
5
- var _chunkHXAAED4Wcjs = require('./chunk-HXAAED4W.cjs');
6
- require('./chunk-SXUZ3CX3.cjs');
7
- require('./chunk-XTHHDIBG.cjs');
8
-
9
-
10
-
11
-
12
- exports.metadata = _chunkHXAAED4Wcjs.metadata; exports.theme = _chunkHXAAED4Wcjs.theme; exports.themeInfo = _chunkHXAAED4Wcjs.themeInfo;