@rapidthoughtlabs/heku 0.2.0 → 0.3.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.
Files changed (4) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +361 -62
  3. package/dist/cli.js +431 -209
  4. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4601,7 +4601,7 @@ var require_schemes = __commonJS({
4601
4601
  serialize: httpSerialize
4602
4602
  }
4603
4603
  );
4604
- var https2 = (
4604
+ var https = (
4605
4605
  /** @type {SchemeHandler} */
4606
4606
  {
4607
4607
  scheme: "https",
@@ -4650,7 +4650,7 @@ var require_schemes = __commonJS({
4650
4650
  /** @type {Record<SchemeName, SchemeHandler>} */
4651
4651
  {
4652
4652
  http: http2,
4653
- https: https2,
4653
+ https,
4654
4654
  ws,
4655
4655
  wss,
4656
4656
  urn,
@@ -8442,7 +8442,7 @@ var require_supports_color = __commonJS({
8442
8442
  "node_modules/supports-color/index.js"(exports2, module2) {
8443
8443
  "use strict";
8444
8444
  init_esm_shims();
8445
- var os7 = __require("os");
8445
+ var os6 = __require("os");
8446
8446
  var tty = __require("tty");
8447
8447
  var hasFlag = require_has_flag();
8448
8448
  var { env } = process;
@@ -8499,7 +8499,7 @@ var require_supports_color = __commonJS({
8499
8499
  return min;
8500
8500
  }
8501
8501
  if (process.platform === "win32") {
8502
- const osRelease = os7.release().split(".");
8502
+ const osRelease = os6.release().split(".");
8503
8503
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
8504
8504
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
8505
8505
  }
@@ -26827,10 +26827,10 @@ var require_view = __commonJS({
26827
26827
  var debug = require_src()("express:view");
26828
26828
  var path24 = __require("path");
26829
26829
  var fs23 = __require("fs");
26830
- var dirname3 = path24.dirname;
26830
+ var dirname4 = path24.dirname;
26831
26831
  var basename3 = path24.basename;
26832
26832
  var extname2 = path24.extname;
26833
- var join3 = path24.join;
26833
+ var join4 = path24.join;
26834
26834
  var resolve3 = path24.resolve;
26835
26835
  module2.exports = View;
26836
26836
  function View(name, options) {
@@ -26866,7 +26866,7 @@ var require_view = __commonJS({
26866
26866
  for (var i = 0; i < roots.length && !path25; i++) {
26867
26867
  var root = roots[i];
26868
26868
  var loc = resolve3(root, name);
26869
- var dir = dirname3(loc);
26869
+ var dir = dirname4(loc);
26870
26870
  var file2 = basename3(loc);
26871
26871
  path25 = this.resolve(dir, file2);
26872
26872
  }
@@ -26892,12 +26892,12 @@ var require_view = __commonJS({
26892
26892
  };
26893
26893
  View.prototype.resolve = function resolve4(dir, file2) {
26894
26894
  var ext = this.ext;
26895
- var path25 = join3(dir, file2);
26895
+ var path25 = join4(dir, file2);
26896
26896
  var stat4 = tryStat(path25);
26897
26897
  if (stat4 && stat4.isFile()) {
26898
26898
  return path25;
26899
26899
  }
26900
- path25 = join3(dir, basename3(file2, ext), "index" + ext);
26900
+ path25 = join4(dir, basename3(file2, ext), "index" + ext);
26901
26901
  stat4 = tryStat(path25);
26902
26902
  if (stat4 && stat4.isFile()) {
26903
26903
  return path25;
@@ -30573,7 +30573,7 @@ var require_send = __commonJS({
30573
30573
  var Stream = __require("stream");
30574
30574
  var util2 = __require("util");
30575
30575
  var extname2 = path24.extname;
30576
- var join3 = path24.join;
30576
+ var join4 = path24.join;
30577
30577
  var normalize2 = path24.normalize;
30578
30578
  var resolve3 = path24.resolve;
30579
30579
  var sep = path24.sep;
@@ -30745,7 +30745,7 @@ var require_send = __commonJS({
30745
30745
  return res;
30746
30746
  }
30747
30747
  parts = path25.split(sep);
30748
- path25 = normalize2(join3(root, path25));
30748
+ path25 = normalize2(join4(root, path25));
30749
30749
  } else {
30750
30750
  if (UP_PATH_REGEXP.test(path25)) {
30751
30751
  debug('malicious path "%s"', path25);
@@ -30878,7 +30878,7 @@ var require_send = __commonJS({
30878
30878
  if (err) return self2.onStatError(err);
30879
30879
  return self2.error(404);
30880
30880
  }
30881
- var p = join3(path25, self2._index[i]);
30881
+ var p = join4(path25, self2._index[i]);
30882
30882
  debug('stat "%s"', p);
30883
30883
  fs23.stat(p, function(err2, stat4) {
30884
30884
  if (err2) return next(err2);
@@ -32320,7 +32320,7 @@ var require_cross_spawn = __commonJS({
32320
32320
  enoent.hookChildProcess(spawned, parsed);
32321
32321
  return spawned;
32322
32322
  }
32323
- function spawnSync2(command2, args2, options) {
32323
+ function spawnSync(command2, args2, options) {
32324
32324
  const parsed = parse3(command2, args2, options);
32325
32325
  const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
32326
32326
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
@@ -32328,7 +32328,7 @@ var require_cross_spawn = __commonJS({
32328
32328
  }
32329
32329
  module2.exports = spawn4;
32330
32330
  module2.exports.spawn = spawn4;
32331
- module2.exports.sync = spawnSync2;
32331
+ module2.exports.sync = spawnSync;
32332
32332
  module2.exports._parse = parse3;
32333
32333
  module2.exports._enoent = enoent;
32334
32334
  }
@@ -33933,7 +33933,7 @@ var require_service_config = __commonJS({
33933
33933
  exports2.validateRetryThrottling = validateRetryThrottling;
33934
33934
  exports2.validateServiceConfig = validateServiceConfig;
33935
33935
  exports2.extractAndSelectServiceConfig = extractAndSelectServiceConfig;
33936
- var os7 = __require("os");
33936
+ var os6 = __require("os");
33937
33937
  var constants_1 = require_constants();
33938
33938
  var DURATION_REGEX = /^\d+(\.\d{1,9})?s$/;
33939
33939
  var CLIENT_LANGUAGE_STRING = "node";
@@ -34232,7 +34232,7 @@ var require_service_config = __commonJS({
34232
34232
  if (Array.isArray(validatedConfig.clientHostname)) {
34233
34233
  let hostnameMatched = false;
34234
34234
  for (const hostname3 of validatedConfig.clientHostname) {
34235
- if (hostname3 === os7.hostname()) {
34235
+ if (hostname3 === os6.hostname()) {
34236
34236
  hostnameMatched = true;
34237
34237
  }
34238
34238
  }
@@ -48781,7 +48781,7 @@ var require_subchannel_call = __commonJS({
48781
48781
  Object.defineProperty(exports2, "__esModule", { value: true });
48782
48782
  exports2.Http2SubchannelCall = void 0;
48783
48783
  var http2 = __require("http2");
48784
- var os7 = __require("os");
48784
+ var os6 = __require("os");
48785
48785
  var constants_1 = require_constants();
48786
48786
  var metadata_1 = require_metadata2();
48787
48787
  var stream_decoder_1 = require_stream_decoder();
@@ -48789,7 +48789,7 @@ var require_subchannel_call = __commonJS({
48789
48789
  var constants_2 = require_constants();
48790
48790
  var TRACER_NAME = "subchannel_call";
48791
48791
  function getSystemErrorName(errno) {
48792
- for (const [name, num] of Object.entries(os7.constants.errno)) {
48792
+ for (const [name, num] of Object.entries(os6.constants.errno)) {
48793
48793
  if (num === errno) {
48794
48794
  return name;
48795
48795
  }
@@ -79142,7 +79142,7 @@ var require_named_placeholders = __commonJS({
79142
79142
  }
79143
79143
  return s;
79144
79144
  }
79145
- function join3(tree) {
79145
+ function join4(tree) {
79146
79146
  if (tree.length === 1) {
79147
79147
  return tree;
79148
79148
  }
@@ -79168,7 +79168,7 @@ var require_named_placeholders = __commonJS({
79168
79168
  if (cache2 && (tree = cache2.get(query))) {
79169
79169
  return toArrayParams(tree, paramsObj);
79170
79170
  }
79171
- tree = join3(parse3(query));
79171
+ tree = join4(parse3(query));
79172
79172
  if (cache2) {
79173
79173
  cache2.set(query, tree);
79174
79174
  }
@@ -81773,9 +81773,9 @@ var require_bindings = __commonJS({
81773
81773
  init_esm_shims();
81774
81774
  var fs23 = __require("fs");
81775
81775
  var path24 = __require("path");
81776
- var fileURLToPath3 = require_file_uri_to_path();
81777
- var join3 = path24.join;
81778
- var dirname3 = path24.dirname;
81776
+ var fileURLToPath4 = require_file_uri_to_path();
81777
+ var join4 = path24.join;
81778
+ var dirname4 = path24.dirname;
81779
81779
  var exists = fs23.accessSync && function(path25) {
81780
81780
  try {
81781
81781
  fs23.accessSync(path25);
@@ -81834,7 +81834,7 @@ var require_bindings = __commonJS({
81834
81834
  var requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
81835
81835
  var tries = [], i = 0, l = opts.try.length, n, b, err;
81836
81836
  for (; i < l; i++) {
81837
- n = join3.apply(
81837
+ n = join4.apply(
81838
81838
  null,
81839
81839
  opts.try[i].map(function(p) {
81840
81840
  return opts[p] || p;
@@ -81885,17 +81885,17 @@ var require_bindings = __commonJS({
81885
81885
  Error.stackTraceLimit = origSTL;
81886
81886
  var fileSchema = "file://";
81887
81887
  if (fileName.indexOf(fileSchema) === 0) {
81888
- fileName = fileURLToPath3(fileName);
81888
+ fileName = fileURLToPath4(fileName);
81889
81889
  }
81890
81890
  return fileName;
81891
81891
  };
81892
81892
  exports2.getRoot = function getRoot(file2) {
81893
- var dir = dirname3(file2), prev;
81893
+ var dir = dirname4(file2), prev;
81894
81894
  while (true) {
81895
81895
  if (dir === ".") {
81896
81896
  dir = process.cwd();
81897
81897
  }
81898
- if (exists(join3(dir, "package.json")) || exists(join3(dir, "node_modules"))) {
81898
+ if (exists(join4(dir, "package.json")) || exists(join4(dir, "node_modules"))) {
81899
81899
  return dir;
81900
81900
  }
81901
81901
  if (prev === dir) {
@@ -81904,7 +81904,7 @@ var require_bindings = __commonJS({
81904
81904
  );
81905
81905
  }
81906
81906
  prev = dir;
81907
- dir = join3(dir, "..");
81907
+ dir = join4(dir, "..");
81908
81908
  }
81909
81909
  };
81910
81910
  }
@@ -93824,7 +93824,7 @@ var require_client_metadata = __commonJS({
93824
93824
  exports2.makeClientMetadata = makeClientMetadata;
93825
93825
  exports2.addContainerMetadata = addContainerMetadata;
93826
93826
  exports2.getFAASEnv = getFAASEnv;
93827
- var os7 = __require("os");
93827
+ var os6 = __require("os");
93828
93828
  var process5 = __require("process");
93829
93829
  var bson_1 = require_bson2();
93830
93830
  var error_1 = require_error2();
@@ -93894,7 +93894,7 @@ var require_client_metadata = __commonJS({
93894
93894
  if (!metadataDocument.ifItFitsItSits("platform", runtimeInfo)) {
93895
93895
  throw new error_1.MongoInvalidArgumentError("Unable to include driverInfo platform, metadata cannot exceed 512 bytes");
93896
93896
  }
93897
- const osInfo = (/* @__PURE__ */ new Map()).set("name", process5.platform).set("architecture", process5.arch).set("version", os7.release()).set("type", os7.type());
93897
+ const osInfo = (/* @__PURE__ */ new Map()).set("name", process5.platform).set("architecture", process5.arch).set("version", os6.release()).set("type", os6.type());
93898
93898
  if (!metadataDocument.ifItFitsItSits("os", osInfo)) {
93899
93899
  for (const key of osInfo.keys()) {
93900
93900
  osInfo.delete(key);
@@ -93997,13 +93997,13 @@ var require_client_metadata = __commonJS({
93997
93997
  function getRuntimeInfo() {
93998
93998
  if ("Deno" in globalThis) {
93999
93999
  const version2 = typeof Deno?.version?.deno === "string" ? Deno?.version?.deno : "0.0.0-unknown";
94000
- return `Deno v${version2}, ${os7.endianness()}`;
94000
+ return `Deno v${version2}, ${os6.endianness()}`;
94001
94001
  }
94002
94002
  if ("Bun" in globalThis) {
94003
94003
  const version2 = typeof Bun?.version === "string" ? Bun?.version : "0.0.0-unknown";
94004
- return `Bun v${version2}, ${os7.endianness()}`;
94004
+ return `Bun v${version2}, ${os6.endianness()}`;
94005
94005
  }
94006
- return `Node.js ${process5.version}, ${os7.endianness()}`;
94006
+ return `Node.js ${process5.version}, ${os6.endianness()}`;
94007
94007
  }
94008
94008
  }
94009
94009
  });
@@ -130795,7 +130795,7 @@ function isConnectorType(value) {
130795
130795
  // src/lib/config-rules.ts
130796
130796
  init_esm_shims();
130797
130797
  init_env_store();
130798
- var RESERVED_IDS = ["one"];
130798
+ var RESERVED_IDS = ["heku"];
130799
130799
  function validateBaseId(id) {
130800
130800
  if (!id || typeof id !== "string" || id.trim() === "") {
130801
130801
  return "id must be a non-empty string";
@@ -131059,8 +131059,10 @@ function getInstalledEntry(slug, registry2 = "default") {
131059
131059
 
131060
131060
  // src/lib/version.ts
131061
131061
  init_esm_shims();
131062
- var VERSION = true ? "0.2.0" : "0.0.0-dev";
131063
- var PKG_NAME = true ? "@rapidthoughtlabs/heku" : "@rapidthoughtlabs/heku";
131062
+ import { readFileSync } from "fs";
131063
+ import { fileURLToPath as fileURLToPath2 } from "url";
131064
+ import { join, dirname } from "path";
131065
+ var VERSION = true ? "0.3.1" : readPkgVersion();
131064
131066
 
131065
131067
  // src/connectors/mcp.ts
131066
131068
  init_esm_shims();
@@ -133924,8 +133926,40 @@ var serverSettings = {
133924
133926
  function getServerSettings() {
133925
133927
  return { ...serverSettings };
133926
133928
  }
133929
+ var DISCOVERY_FLAT_SET = /* @__PURE__ */ new Set(["heku.search", "heku.list_tools", "heku.list_configs", "heku.invoke"]);
133930
+ var DISCOVERY_TRIO_SET = /* @__PURE__ */ new Set(["heku.search", "heku.list_tools", "heku.list_configs"]);
133927
133931
  function createAdminRouter(ctx) {
133928
133932
  const router = (0, import_express.Router)();
133933
+ router.get("/tools-manifest", (req, res) => {
133934
+ const styleParam = req.query.style;
133935
+ const style = styleParam === "namespaced" || styleParam === "flat" ? styleParam : serverSettings.manifestStyle;
133936
+ const tools = ctx.registry.list();
133937
+ if (style === "namespaced") {
133938
+ const visible2 = tools.filter(
133939
+ (rt) => DISCOVERY_TRIO_SET.has(`${rt.configId}.${rt.tool.name}`)
133940
+ );
133941
+ res.json(
133942
+ visible2.map((rt) => ({
133943
+ name: `${rt.configId}.${rt.tool.name}`,
133944
+ description: rt.tool.description,
133945
+ inputSchema: buildInputSchema2(rt.tool.params ?? []),
133946
+ configId: rt.configId
133947
+ }))
133948
+ );
133949
+ return;
133950
+ }
133951
+ const visible = tools.filter(
133952
+ (rt) => DISCOVERY_FLAT_SET.has(`${rt.configId}.${rt.tool.name}`)
133953
+ );
133954
+ res.json(
133955
+ visible.map((rt) => ({
133956
+ name: rt.tool.name,
133957
+ description: rt.tool.description,
133958
+ inputSchema: buildInputSchema2(rt.tool.params ?? []),
133959
+ configId: rt.configId
133960
+ }))
133961
+ );
133962
+ });
133929
133963
  router.get("/server-settings", (_req, res) => {
133930
133964
  res.json({
133931
133965
  hotReload: ctx.watcher ? !ctx.watcher.isPaused() : serverSettings.hotReload,
@@ -134326,6 +134360,8 @@ var ToolRegistry = class {
134326
134360
  }
134327
134361
  this.tools.set(qualifiedName, {
134328
134362
  configId: config2.id,
134363
+ configName: config2.name,
134364
+ configDescription: config2.description,
134329
134365
  connectorConfig: config2.connector,
134330
134366
  tool
134331
134367
  });
@@ -134349,8 +134385,8 @@ var ToolRegistry = class {
134349
134385
  return this.tools.size;
134350
134386
  }
134351
134387
  };
134352
- var DISCOVERY_FLAT = /* @__PURE__ */ new Set(["one.search", "one.list_tools", "one.list_configs", "one.invoke"]);
134353
- var DISCOVERY_TRIO = /* @__PURE__ */ new Set(["one.search", "one.list_tools", "one.list_configs"]);
134388
+ var DISCOVERY_FLAT = /* @__PURE__ */ new Set(["heku.search", "heku.list_tools", "heku.list_configs", "heku.invoke"]);
134389
+ var DISCOVERY_TRIO = /* @__PURE__ */ new Set(["heku.search", "heku.list_tools", "heku.list_configs"]);
134354
134390
  function buildManifestView(style, registry2) {
134355
134391
  if (style === "namespaced") {
134356
134392
  return {
@@ -134361,23 +134397,24 @@ function buildManifestView(style, registry2) {
134361
134397
  }
134362
134398
  return {
134363
134399
  visible: registry2.list().filter((rt) => DISCOVERY_FLAT.has(`${rt.configId}.${rt.tool.name}`)),
134364
- rewrite: (qualified) => qualified.replace(/^one\./, ""),
134365
- resolve: (incoming) => incoming.includes(".") ? incoming : `one.${incoming}`
134400
+ rewrite: (qualified) => qualified.replace(/^heku\./, ""),
134401
+ resolve: (incoming) => incoming.includes(".") ? incoming : `heku.${incoming}`
134366
134402
  };
134367
134403
  }
134368
134404
  var BLOCKED_WHEN_LOCKED = /* @__PURE__ */ new Set([
134369
- "one.create_config",
134370
- "one.update_config",
134371
- "one.delete_config",
134372
- "one.add_tool",
134373
- "one.remove_tool",
134374
- "one.update_tool",
134375
- "one.registry_install",
134376
- "one.auth_set"
134405
+ "heku.create_config",
134406
+ "heku.update_config",
134407
+ "heku.delete_config",
134408
+ "heku.add_tool",
134409
+ "heku.remove_tool",
134410
+ "heku.update_tool",
134411
+ "heku.registry_install",
134412
+ "heku.registry_update",
134413
+ "heku.auth_set"
134377
134414
  ]);
134378
134415
  function blockedTool(qualifiedName, args2) {
134379
134416
  if (BLOCKED_WHEN_LOCKED.has(qualifiedName)) return qualifiedName;
134380
- if (qualifiedName === "one.invoke") {
134417
+ if (qualifiedName === "heku.invoke") {
134381
134418
  const target = args2["tool"];
134382
134419
  if (typeof target === "string" && BLOCKED_WHEN_LOCKED.has(target)) return target;
134383
134420
  }
@@ -134393,7 +134430,7 @@ function makeServer(registry2, transportCtx) {
134393
134430
  const { visible, rewrite } = buildManifestView(manifestStyle, registry2);
134394
134431
  const tools = visible.map((rt) => ({
134395
134432
  name: rewrite(`${rt.configId}.${rt.tool.name}`),
134396
- description: `[${rt.configId}] ${rt.tool.description}`,
134433
+ description: manifestStyle === "flat" ? rt.tool.description : `[${rt.configId}] ${rt.tool.description}`,
134397
134434
  inputSchema: buildInputSchema(rt.tool.params)
134398
134435
  }));
134399
134436
  return { tools };
@@ -135371,9 +135408,9 @@ var NodeFsHandler = class {
135371
135408
  if (this.fsw.closed) {
135372
135409
  return;
135373
135410
  }
135374
- const dirname3 = sp.dirname(file2);
135411
+ const dirname4 = sp.dirname(file2);
135375
135412
  const basename3 = sp.basename(file2);
135376
- const parent = this.fsw._getWatchedDir(dirname3);
135413
+ const parent = this.fsw._getWatchedDir(dirname4);
135377
135414
  let prevStats = stats;
135378
135415
  if (parent.has(basename3))
135379
135416
  return;
@@ -135400,7 +135437,7 @@ var NodeFsHandler = class {
135400
135437
  prevStats = newStats2;
135401
135438
  }
135402
135439
  } catch (error3) {
135403
- this.fsw._remove(dirname3, basename3);
135440
+ this.fsw._remove(dirname4, basename3);
135404
135441
  }
135405
135442
  } else if (parent.has(basename3)) {
135406
135443
  const at = newStats.atimeMs;
@@ -136363,7 +136400,7 @@ init_loader();
136363
136400
  var DEBOUNCE_MS = 300;
136364
136401
  function isMcpConfigFile(filePath) {
136365
136402
  const base2 = path11.basename(filePath);
136366
- return base2.startsWith("mcp.") && base2.endsWith(".json") && base2 !== "mcp.one.json";
136403
+ return base2.startsWith("mcp.") && base2.endsWith(".json") && base2 !== "mcp.heku.json";
136367
136404
  }
136368
136405
  function isMcpEnvFile(filePath) {
136369
136406
  const base2 = path11.basename(filePath);
@@ -136685,7 +136722,7 @@ function resolveConfigDir(cliOverride, systemConfig) {
136685
136722
  init_esm_shims();
136686
136723
  var import_express5 = __toESM(require_express2(), 1);
136687
136724
  var import_cors = __toESM(require_lib3(), 1);
136688
- import { fileURLToPath as fileURLToPath2 } from "url";
136725
+ import { fileURLToPath as fileURLToPath3 } from "url";
136689
136726
 
136690
136727
  // server/mcp-client.ts
136691
136728
  init_esm_shims();
@@ -137612,7 +137649,21 @@ function createApiRouter(mcp) {
137612
137649
  }
137613
137650
  }
137614
137651
  });
137615
- router.get("/tools/manifest", (_req, res) => {
137652
+ router.get("/tools/manifest", async (req, res) => {
137653
+ const style = req.query.style;
137654
+ if (style === "flat" || style === "namespaced") {
137655
+ try {
137656
+ const tools = await admin.get(`/tools-manifest?style=${style}`);
137657
+ res.json(tools);
137658
+ } catch (err) {
137659
+ if (err instanceof AdminUnavailableError) {
137660
+ res.json([]);
137661
+ return;
137662
+ }
137663
+ res.status(500).json({ error: err.message });
137664
+ }
137665
+ return;
137666
+ }
137616
137667
  res.json(mcp.listTools());
137617
137668
  });
137618
137669
  router.post("/tools/call", async (req, res) => {
@@ -137822,6 +137873,9 @@ async function getConfigMeta(namespace, slug, connectorType, registryName = "def
137822
137873
  const slugWithConnector = connectorType ? `${slug}:${connectorType}` : slug;
137823
137874
  return jsonFetch(`/configs/${namespace}/${slugWithConnector}`, { registryName });
137824
137875
  }
137876
+ async function listVersions(namespace, slug, registryName = "default") {
137877
+ return jsonFetch(`/configs/${namespace}/${slug}/versions`, { registryName });
137878
+ }
137825
137879
  async function fetchVersionPayload(namespace, slug, connectorType, version2, registryName = "default") {
137826
137880
  const slugWithConnector = connectorType ? `${slug}:${connectorType}` : slug;
137827
137881
  const vPath = version2 ?? "latest";
@@ -137982,7 +138036,7 @@ function createRegistryRouter() {
137982
138036
  const slug = colonIdx !== -1 ? rest.slice(0, colonIdx) : rest;
137983
138037
  const connectorType = colonIdx !== -1 ? rest.slice(colonIdx + 1) : void 0;
137984
138038
  const meta3 = await getConfigMeta(namespace, slug, connectorType, registry2);
137985
- res.json({ category: meta3.category, tags: meta3.tags });
138039
+ res.json({ category: meta3.category, tags: meta3.tags, latest_version: meta3.latest_version ?? null });
137986
138040
  }));
137987
138041
  router.post("/check-updates", wrap(async (req, res) => {
137988
138042
  const { installed, registry: registry2 = "default" } = req.body;
@@ -138094,6 +138148,12 @@ function createRegistryRouter() {
138094
138148
  const { payload } = await fetchVersionPayload(namespace, slug, connector_type, void 0, registry2);
138095
138149
  res.json(payload);
138096
138150
  }));
138151
+ router.get("/versions/:namespace/:slug", wrap(async (req, res) => {
138152
+ const { namespace, slug } = req.params;
138153
+ const registry2 = req.query["registry"] ?? "default";
138154
+ const versions = await listVersions(namespace, slug, registry2);
138155
+ res.json(versions);
138156
+ }));
138097
138157
  router.delete("/uninstall/:id", wrap(async (req, res) => {
138098
138158
  const id = req.params["id"];
138099
138159
  const registry2 = req.query["registry"] ?? "default";
@@ -138152,7 +138212,7 @@ async function startBridge(options) {
138152
138212
  }
138153
138213
  };
138154
138214
  }
138155
- var isMain = process.argv[1] === fileURLToPath2(import.meta.url);
138215
+ var isMain = process.argv[1] === fileURLToPath3(import.meta.url);
138156
138216
  if (isMain) {
138157
138217
  const port = Number(process.env["PORT"] ?? 3456);
138158
138218
  const bridge = await startBridge({ port });
@@ -138180,7 +138240,7 @@ init_env_store();
138180
138240
  // src/internal-config.ts
138181
138241
  init_esm_shims();
138182
138242
  var INTERNAL_CONFIG = {
138183
- id: "one",
138243
+ id: "heku",
138184
138244
  name: "heku Self-Management",
138185
138245
  description: "Create configs, add tools, install from registry, manage auth \u2014 heku's own management interface for LLM agents.",
138186
138246
  connector: { type: "internal" },
@@ -138206,12 +138266,12 @@ var INTERNAL_CONFIG = {
138206
138266
  },
138207
138267
  {
138208
138268
  name: "list_configs",
138209
- description: "**Start here.** Returns the names of all active configs as a flat array. Config IDs follow the pattern `<base>-<connector>` where connector is one of: http, cli, file, grpc, graphql, mcp, sql, mongodb. Use these names to scope `one.search` or `one.list_tools`.",
138269
+ description: "**Start here.** Returns all active configs as an array of objects with `id`, `name`, and `description`. Config IDs follow the pattern `<base>-<connector>` (e.g. `github-http`, `linear-graphql`). Use the description to pick the right config, then pass its `id` to `search` or `list_tools`.",
138210
138270
  params: []
138211
138271
  },
138212
138272
  {
138213
138273
  name: "search",
138214
- description: "Find tools by name or intent across all configs (or within a specific one). Returns matching tools with full schemas grouped by match quality: exact name match first, then partial, then description, then related. Indexes both native `one.*` self-management tools and all service tools. Pass config for exact-first matching: 'github-http' returns only github-http tools; 'github' matches both github-http and github-cli.",
138274
+ description: "Find tools by name or intent across all configs (or within a specific one). Returns matching tools with full schemas grouped by quality: exact \u2192 partial \u2192 description \u2192 related. Covers both native `heku.*` self-management tools and all loaded service tools. Narrow by config: `github-http` returns only github-http tools; `github` matches github-http and github-cli. Once you have a tool name, call `invoke` with `config_id.tool_name` to execute it.",
138215
138275
  params: [
138216
138276
  {
138217
138277
  name: "query",
@@ -138229,13 +138289,13 @@ var INTERNAL_CONFIG = {
138229
138289
  },
138230
138290
  {
138231
138291
  name: "invoke",
138232
- description: "Execute any registered tool by its qualified name (config_id.tool_name). Use after one.search or one.list_tools to run the tool you found. Works for all service tools (open-meteo-http.get_forecast, github-http.create_issue, etc.) and all one.* self-management tools.",
138292
+ description: "Execute any registered tool by its qualified name (`config_id.tool_name`). Workflow: (1) list_configs \u2192 pick a config id, (2) search or list_tools \u2192 get the tool name and required args, (3) invoke \u2192 run it. Examples: `github-http.create_issue`, `linear-graphql.create_issue`, `heku.server_status`.",
138233
138293
  params: [
138234
138294
  {
138235
138295
  name: "tool",
138236
138296
  type: "string",
138237
138297
  required: true,
138238
- description: "Qualified tool name in the format config_id.tool_name (e.g. 'open-meteo-http.get_forecast', 'github-http.create_issue', 'one.server_status')"
138298
+ description: "Qualified tool name in the format config_id.tool_name (e.g. 'open-meteo-http.get_forecast', 'github-http.create_issue', 'heku.server_status')"
138239
138299
  },
138240
138300
  {
138241
138301
  name: "args",
@@ -138257,7 +138317,7 @@ var INTERNAL_CONFIG = {
138257
138317
  },
138258
138318
  {
138259
138319
  name: "delete_config",
138260
- description: "Delete a config file and unregister all its tools. Cannot delete the 'one' self-management config \u2014 use self_config: false in heku.config.json instead.",
138320
+ description: "Delete a config file and unregister all its tools. Cannot delete the 'heku' self-management config \u2014 use self_config: false in heku.config.json instead.",
138261
138321
  params: [
138262
138322
  { name: "config_id", type: "string", required: true, description: "Config ID to delete" }
138263
138323
  ]
@@ -138296,9 +138356,9 @@ var INTERNAL_CONFIG = {
138296
138356
  },
138297
138357
  {
138298
138358
  name: "list_tools",
138299
- description: "Returns tools with full schemas ready to call. No args: returns only the native `one.*` self-management surface. With config_id: returns all tools in that config. For targeted lookup by name or intent, use `one.search` instead.",
138359
+ description: "Returns tools with full schemas ready to call. No args: returns only the native `heku.*` self-management surface. With config_id: returns all tools in that config. For targeted lookup by name or intent, use `heku.search` instead.",
138300
138360
  params: [
138301
- { name: "config_id", type: "string", required: false, description: "Config ID to list tools for. Omit to list only native one.* tools." }
138361
+ { name: "config_id", type: "string", required: false, description: "Config ID to list tools for. Omit to list only native heku.* tools." }
138302
138362
  ]
138303
138363
  },
138304
138364
  {
@@ -138345,6 +138405,14 @@ var INTERNAL_CONFIG = {
138345
138405
  { name: "registry", type: "string", required: false, description: "Registry source name (default: 'default')" }
138346
138406
  ]
138347
138407
  },
138408
+ {
138409
+ name: "registry_update",
138410
+ description: "Update registry-installed configs to the latest available version. Preserves local credentials (connector.env) and overlays. Pass config_id to update a single config, or omit to update all installed configs.",
138411
+ params: [
138412
+ { name: "config_id", type: "string", required: false, description: "ID of the config to update (e.g. 'github-http'). Omit to update all installed configs." },
138413
+ { name: "registry", type: "string", required: false, description: "Registry source name (default: 'default')" }
138414
+ ]
138415
+ },
138348
138416
  {
138349
138417
  name: "auth_status",
138350
138418
  description: "Check which configs have missing or misconfigured credentials. Returns per-config auth status and the specific env vars that are missing.",
@@ -141195,7 +141263,17 @@ async function handleGetConfig(ctx, args2) {
141195
141263
  return { success: true, data: raw };
141196
141264
  }
141197
141265
  async function handleListConfigs(ctx, _args) {
141198
- const configs = [...new Set(ctx.registry.list().map((rt) => rt.configId))].sort();
141266
+ const seen = /* @__PURE__ */ new Map();
141267
+ for (const rt of ctx.registry.list()) {
141268
+ if (!seen.has(rt.configId)) {
141269
+ seen.set(rt.configId, {
141270
+ id: rt.configId,
141271
+ ...rt.configName && { name: rt.configName },
141272
+ ...rt.configDescription && { description: rt.configDescription }
141273
+ });
141274
+ }
141275
+ }
141276
+ const configs = [...seen.values()].sort((a, b) => a.id.localeCompare(b.id));
141199
141277
  return { success: true, data: { configs } };
141200
141278
  }
141201
141279
  async function handleUpdateConfig(ctx, args2) {
@@ -141412,7 +141490,7 @@ async function handleUpdateTool(ctx, args2) {
141412
141490
  }
141413
141491
  async function handleListTools(ctx, args2) {
141414
141492
  const filterById = args2.config_id;
141415
- const scopeId = filterById ?? "one";
141493
+ const scopeId = filterById ?? "heku";
141416
141494
  const tools = ctx.registry.list().filter((rt) => rt.configId === scopeId).map((rt) => ({
141417
141495
  qualified_name: `${rt.configId}.${rt.tool.name}`,
141418
141496
  config_id: rt.configId,
@@ -141633,6 +141711,112 @@ async function handleRegistryInstall(ctx, args2) {
141633
141711
  return { success: false, data: { error: err.message } };
141634
141712
  }
141635
141713
  }
141714
+ async function handleRegistryUpdate(ctx, args2) {
141715
+ const configId = args2.config_id;
141716
+ const registry2 = args2.registry ?? "default";
141717
+ const { installed } = loadManifest();
141718
+ const forRegistry = installed.filter((e) => e.registry === registry2);
141719
+ let toCheck;
141720
+ if (configId) {
141721
+ const entry = forRegistry.find((e) => {
141722
+ const withoutNs = e.slug.replace(/^@[^/]+\//, "");
141723
+ const colonIdx = withoutNs.indexOf(":");
141724
+ if (colonIdx === -1) return false;
141725
+ const base2 = withoutNs.slice(0, colonIdx);
141726
+ const ct = withoutNs.slice(colonIdx + 1);
141727
+ return `${base2}-${ct}` === configId;
141728
+ });
141729
+ if (!entry) {
141730
+ return {
141731
+ success: false,
141732
+ data: { error: `"${configId}" is not a registry-installed config or was not found in the manifest. Only configs installed from the registry can be updated this way.` }
141733
+ };
141734
+ }
141735
+ toCheck = [entry];
141736
+ } else {
141737
+ if (forRegistry.length === 0) {
141738
+ return { success: true, data: { message: "No registry-installed configs to update", updated: [], up_to_date: [] } };
141739
+ }
141740
+ toCheck = forRegistry;
141741
+ }
141742
+ let updateCheck;
141743
+ try {
141744
+ updateCheck = await checkUpdates(
141745
+ toCheck.map((e) => ({ slug: e.slug, version: e.version })),
141746
+ registry2
141747
+ );
141748
+ } catch (err) {
141749
+ if (err instanceof RegistryError) {
141750
+ return { success: false, data: { error: err.message, status: err.status } };
141751
+ }
141752
+ return { success: false, data: { error: err.message } };
141753
+ }
141754
+ if (updateCheck.updates.length === 0) {
141755
+ return {
141756
+ success: true,
141757
+ data: { message: "All configs are up to date", up_to_date: updateCheck.up_to_date }
141758
+ };
141759
+ }
141760
+ const updated = [];
141761
+ const errors2 = [];
141762
+ for (const info of updateCheck.updates) {
141763
+ const withoutAt = info.slug.startsWith("@") ? info.slug.slice(1) : info.slug;
141764
+ const slashIdx = withoutAt.indexOf("/");
141765
+ if (slashIdx === -1) continue;
141766
+ const namespace = withoutAt.slice(0, slashIdx);
141767
+ const rest = withoutAt.slice(slashIdx + 1);
141768
+ const colonIdx = rest.indexOf(":");
141769
+ const rawSlug = colonIdx !== -1 ? rest.slice(0, colonIdx) : rest;
141770
+ const connType = colonIdx !== -1 ? rest.slice(colonIdx + 1) : void 0;
141771
+ const installedId = `${rawSlug}-${connType ?? ""}`;
141772
+ const outFile = path17.join(ctx.configDir, `mcp.${installedId}.json`);
141773
+ try {
141774
+ const { payload, version: resolvedVersion } = await fetchVersionPayload(
141775
+ namespace,
141776
+ rawSlug,
141777
+ connType,
141778
+ info.latest_version,
141779
+ registry2
141780
+ );
141781
+ const payloadObj = payload;
141782
+ payloadObj.id = installedId;
141783
+ if (fs15.existsSync(outFile)) {
141784
+ try {
141785
+ const existing = JSON.parse(fs15.readFileSync(outFile, "utf-8"));
141786
+ const existingConnector = existing.connector;
141787
+ if (existingConnector?.env) {
141788
+ const newConnector = payloadObj.connector ?? {};
141789
+ newConnector.env = existingConnector.env;
141790
+ payloadObj.connector = newConnector;
141791
+ }
141792
+ const existingOverlays = existing.overlays ?? {};
141793
+ const newOverlays = payloadObj.overlays ?? {};
141794
+ payloadObj.overlays = { ...existingOverlays, ...newOverlays };
141795
+ } catch {
141796
+ }
141797
+ }
141798
+ fs15.mkdirSync(ctx.configDir, { recursive: true });
141799
+ fs15.writeFileSync(outFile, JSON.stringify(payloadObj, null, 2) + "\n", "utf-8");
141800
+ addToManifest(info.slug, resolvedVersion, connType ?? "", registry2);
141801
+ updated.push({ slug: info.slug, id: installedId, from: info.installed_version, to: resolvedVersion });
141802
+ } catch (err) {
141803
+ if (err instanceof RegistryError) {
141804
+ errors2.push({ slug: info.slug, error: err.message });
141805
+ } else {
141806
+ errors2.push({ slug: info.slug, error: err.message });
141807
+ }
141808
+ }
141809
+ }
141810
+ return {
141811
+ success: errors2.length === 0,
141812
+ data: {
141813
+ message: updated.length > 0 ? `Updated ${updated.length} config(s).${errors2.length > 0 ? ` ${errors2.length} failed.` : ""} Server will hot-reload automatically.` : `All configs are up to date.`,
141814
+ updated,
141815
+ up_to_date: updateCheck.up_to_date,
141816
+ ...errors2.length > 0 && { errors: errors2 }
141817
+ }
141818
+ };
141819
+ }
141636
141820
  async function handleRegistryCheckUpdates(_ctx, args2) {
141637
141821
  const registry2 = args2.registry ?? "default";
141638
141822
  try {
@@ -141874,7 +142058,7 @@ async function handleInvoke(ctx, args2) {
141874
142058
  success: false,
141875
142059
  data: {
141876
142060
  error: `Tool "${toolName}" not found`,
141877
- hint: "Use one.search or one.list_tools to find available tool names",
142061
+ hint: "Use heku.search or heku.list_tools to find available tool names",
141878
142062
  available_count: available.length
141879
142063
  }
141880
142064
  };
@@ -141927,6 +142111,7 @@ var HANDLERS = {
141927
142111
  registry_browse: handleRegistryBrowse,
141928
142112
  registry_install: handleRegistryInstall,
141929
142113
  registry_check_updates: handleRegistryCheckUpdates,
142114
+ registry_update: handleRegistryUpdate,
141930
142115
  // Auth
141931
142116
  auth_status: handleAuthStatus,
141932
142117
  auth_set: handleAuthSet,
@@ -142419,8 +142604,8 @@ async function run(args2) {
142419
142604
  }
142420
142605
  log.info("server", `Loading configs from: ${configDir}`);
142421
142606
  const handAuthored = loadConfigs(configDir).filter((c) => {
142422
- if (c.id === "one") {
142423
- log.warn("server", `mcp.one.json in ${configDir} is ignored \u2014 internal config is built-in`);
142607
+ if (c.id === "heku") {
142608
+ log.warn("server", `mcp.heku.json in ${configDir} is ignored \u2014 internal config is built-in`);
142424
142609
  return false;
142425
142610
  }
142426
142611
  return true;
@@ -142430,7 +142615,7 @@ async function run(args2) {
142430
142615
  ...handAuthored
142431
142616
  ];
142432
142617
  if (handAuthored.length === 0) {
142433
- log.info("server", `No user configs yet \u2014 drop mcp.*.json files in ${configDir} or call one.registry_install`);
142618
+ log.info("server", `No user configs yet \u2014 drop mcp.*.json files in ${configDir} or call heku.registry_install`);
142434
142619
  }
142435
142620
  for (const config2 of allConfigs) {
142436
142621
  if (config2.connector.type === "mcp") {
@@ -142563,13 +142748,13 @@ async function run(args2) {
142563
142748
  }
142564
142749
  if (systemConfig.self_config === false) {
142565
142750
  const before = allConfigs.length;
142566
- allConfigs.splice(0, allConfigs.length, ...allConfigs.filter((c) => c.id !== "one"));
142751
+ allConfigs.splice(0, allConfigs.length, ...allConfigs.filter((c) => c.id !== "heku"));
142567
142752
  if (allConfigs.length < before) {
142568
142753
  log.info("server", "self_config: false \u2014 heku self-management disabled");
142569
142754
  }
142570
142755
  } else if (systemConfig.self_config && typeof systemConfig.self_config === "object") {
142571
142756
  const sc = systemConfig.self_config;
142572
- const oneConfig = allConfigs.find((c) => c.id === "one");
142757
+ const oneConfig = allConfigs.find((c) => c.id === "heku");
142573
142758
  if (oneConfig) {
142574
142759
  if (sc.allow) {
142575
142760
  oneConfig.tools = oneConfig.tools.filter((t) => sc.allow.includes(t.name));
@@ -143358,7 +143543,7 @@ async function run5(args2) {
143358
143543
  } else {
143359
143544
  let candidates = [];
143360
143545
  if (fs18.existsSync(configDir)) {
143361
- candidates = fs18.readdirSync(configDir).filter((f) => f.startsWith("mcp.") && f.endsWith(".json") && f !== "mcp.one.json").map((f) => path20.join(configDir, f));
143546
+ candidates = fs18.readdirSync(configDir).filter((f) => f.startsWith("mcp.") && f.endsWith(".json") && f !== "mcp.heku.json").map((f) => path20.join(configDir, f));
143362
143547
  }
143363
143548
  if (candidates.length === 0) {
143364
143549
  console.error(red("\u2717") + ` No config file found. Try: ${bold("heku publish <name>")}`);
@@ -144088,159 +144273,195 @@ async function run8(args2) {
144088
144273
 
144089
144274
  // src/commands/update.ts
144090
144275
  init_esm_shims();
144091
- import { spawnSync } from "child_process";
144092
-
144093
- // src/lib/update-check.ts
144094
- init_esm_shims();
144095
- import https from "https";
144096
144276
  import fs22 from "fs";
144097
144277
  import path23 from "path";
144098
- import os6 from "os";
144099
- var CACHE_FILE = path23.join(os6.homedir(), ".heku", "update-check.json");
144100
- var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
144101
- function readCache() {
144102
- try {
144103
- return JSON.parse(fs22.readFileSync(CACHE_FILE, "utf-8"));
144104
- } catch {
144105
- return null;
144106
- }
144107
- }
144108
- function writeCache(latestVersion) {
144109
- try {
144110
- fs22.mkdirSync(path23.dirname(CACHE_FILE), { recursive: true });
144111
- fs22.writeFileSync(
144112
- CACHE_FILE,
144113
- JSON.stringify({ checkedAt: Date.now(), latestVersion }),
144114
- "utf-8"
144115
- );
144116
- } catch {
144117
- }
144118
- }
144119
- function fetchLatestVersion() {
144120
- return new Promise((resolve3, reject) => {
144121
- const req = https.get(
144122
- `https://registry.npmjs.org/${PKG_NAME}/latest`,
144123
- { headers: { Accept: "application/json" } },
144124
- (res) => {
144125
- let data = "";
144126
- res.on("data", (chunk) => {
144127
- data += chunk;
144128
- });
144129
- res.on("end", () => {
144130
- try {
144131
- if (res.statusCode !== 200) {
144132
- reject(new Error(`npm registry returned HTTP ${res.statusCode}`));
144133
- return;
144134
- }
144135
- const json2 = JSON.parse(data);
144136
- if (!json2.version) {
144137
- reject(new Error("npm registry response missing version field"));
144138
- return;
144139
- }
144140
- resolve3(json2.version);
144141
- } catch (e) {
144142
- reject(e);
144143
- }
144144
- });
144145
- }
144146
- );
144147
- req.on("error", reject);
144148
- req.setTimeout(5e3, () => {
144149
- req.destroy();
144150
- reject(new Error("timeout"));
144151
- });
144152
- });
144153
- }
144154
- function semverGt(a, b) {
144155
- const parse3 = (v) => v.replace(/[^0-9.]/g, "").split(".").map(Number);
144156
- const pa = parse3(a);
144157
- const pb = parse3(b);
144158
- for (let i = 0; i < 3; i++) {
144159
- const na = pa[i] ?? 0;
144160
- const nb = pb[i] ?? 0;
144161
- if (na > nb) return true;
144162
- if (na < nb) return false;
144163
- }
144278
+ function compoundId2(entry) {
144279
+ const withoutNs = entry.slug.replace(/^@[^/]+\//, "");
144280
+ const colonIdx = withoutNs.indexOf(":");
144281
+ const rawSlug = colonIdx !== -1 ? withoutNs.slice(0, colonIdx) : withoutNs;
144282
+ const ct = colonIdx !== -1 ? withoutNs.slice(colonIdx + 1) : entry.connector_type;
144283
+ return `${rawSlug}-${ct}`;
144284
+ }
144285
+ function matchesTarget(entry, target) {
144286
+ const slug = entry.slug;
144287
+ if (slug === target || slug === `@${target}`) return true;
144288
+ const withoutNs = slug.replace(/^@[^/]+\//, "");
144289
+ const colonIdx = withoutNs.indexOf(":");
144290
+ const rawSlug = colonIdx !== -1 ? withoutNs.slice(0, colonIdx) : withoutNs;
144291
+ const ct = colonIdx !== -1 ? withoutNs.slice(colonIdx + 1) : "";
144292
+ if (`${rawSlug}-${ct}` === target) return true;
144293
+ if (withoutNs === target) return true;
144294
+ const withoutConnector = slug.replace(/:.*$/, "");
144295
+ if (withoutConnector === target || withoutConnector === `@${target}`) return true;
144296
+ if (!target.includes(":") && !target.includes("-") && rawSlug === target) return true;
144164
144297
  return false;
144165
144298
  }
144166
- function printUpdateNotice(latestVersion) {
144167
- const line1 = ` Update available: ${VERSION} \u2192 ${latestVersion}`;
144168
- const line2 = ` Run: npm install -g ${PKG_NAME}@latest`;
144169
- const width = Math.max(line1.length, line2.length) + 2;
144170
- const bar = "\u2500".repeat(width);
144171
- process.stderr.write(
144172
- `
144173
- \u250C${bar}\u2510
144174
- \u2502${line1.padEnd(width)}\u2502
144175
- \u2502${line2.padEnd(width)}\u2502
144176
- \u2514${bar}\u2518
144177
-
144178
- `
144299
+ async function downloadAndInstall(entry, latestVersion, configDir) {
144300
+ const withoutAt = entry.slug.startsWith("@") ? entry.slug.slice(1) : entry.slug;
144301
+ const slashIdx = withoutAt.indexOf("/");
144302
+ const namespace = withoutAt.slice(0, slashIdx);
144303
+ const rest = withoutAt.slice(slashIdx + 1);
144304
+ const colonIdx = rest.indexOf(":");
144305
+ const rawSlug = colonIdx !== -1 ? rest.slice(0, colonIdx) : rest;
144306
+ const connType = colonIdx !== -1 ? rest.slice(colonIdx + 1) : entry.connector_type;
144307
+ const id = `${rawSlug}-${connType}`;
144308
+ const outFile = path23.join(configDir, `mcp.${id}.json`);
144309
+ const { payload, version: resolvedVersion } = await fetchVersionPayload(
144310
+ namespace,
144311
+ rawSlug,
144312
+ connType,
144313
+ latestVersion,
144314
+ entry.registry
144179
144315
  );
144180
- }
144181
- function checkForUpdate() {
144182
- const cache2 = readCache();
144183
- if (cache2 && typeof cache2.latestVersion === "string" && cache2.latestVersion.length > 0 && Date.now() - cache2.checkedAt < CACHE_TTL_MS) {
144184
- if (semverGt(cache2.latestVersion, VERSION)) {
144185
- printUpdateNotice(cache2.latestVersion);
144316
+ const payloadObj = payload;
144317
+ payloadObj.id = id;
144318
+ if (fs22.existsSync(outFile)) {
144319
+ try {
144320
+ const existing = JSON.parse(fs22.readFileSync(outFile, "utf-8"));
144321
+ const existingConn = existing.connector;
144322
+ if (existingConn?.env) {
144323
+ const newConn = payloadObj.connector ?? {};
144324
+ newConn.env = existingConn.env;
144325
+ payloadObj.connector = newConn;
144326
+ }
144327
+ const existingOverlays = existing.overlays ?? {};
144328
+ const newOverlays = payloadObj.overlays ?? {};
144329
+ payloadObj.overlays = { ...existingOverlays, ...newOverlays };
144330
+ } catch {
144186
144331
  }
144332
+ }
144333
+ fs22.mkdirSync(configDir, { recursive: true });
144334
+ fs22.writeFileSync(outFile, JSON.stringify(payloadObj, null, 2) + "\n", "utf-8");
144335
+ addToManifest(entry.slug, resolvedVersion, connType, entry.registry, entry.forked_from ?? null);
144336
+ return { id, from: entry.version, to: resolvedVersion };
144337
+ }
144338
+ async function run9(args2) {
144339
+ const registryIdx = args2.indexOf("--registry");
144340
+ const registry2 = registryIdx !== -1 ? args2[registryIdx + 1] ?? "default" : "default";
144341
+ const skipIndices = /* @__PURE__ */ new Set();
144342
+ if (registryIdx !== -1) {
144343
+ skipIndices.add(registryIdx);
144344
+ skipIndices.add(registryIdx + 1);
144345
+ }
144346
+ const target = args2.find((a, i) => !skipIndices.has(i) && !a.startsWith("--"));
144347
+ const systemConfig = loadSystemConfig(process.cwd());
144348
+ const configDir = resolveConfigDir(void 0, systemConfig);
144349
+ const { installed } = loadManifest();
144350
+ const forRegistry = installed.filter((e) => e.registry === registry2);
144351
+ if (forRegistry.length === 0) {
144352
+ console.log();
144353
+ console.log(dim(" No registry-installed configs found."));
144354
+ console.log(dim(` Install one with: ${bold("heku install @ns/slug")}`));
144355
+ console.log();
144187
144356
  return;
144188
144357
  }
144189
- fetchLatestVersion().then((latest) => {
144190
- writeCache(latest);
144191
- if (semverGt(latest, VERSION)) {
144192
- printUpdateNotice(latest);
144358
+ let toCheck;
144359
+ if (target) {
144360
+ toCheck = forRegistry.filter((e) => matchesTarget(e, target));
144361
+ if (toCheck.length === 0) {
144362
+ console.log();
144363
+ console.error(red("\u2717") + ` No installed config matches "${bold(target)}".`);
144364
+ console.error(dim(` Run ${bold("heku list")} to see installed configs.`));
144365
+ console.log();
144366
+ process.exit(1);
144193
144367
  }
144194
- }).catch(() => {
144195
- });
144196
- }
144197
-
144198
- // src/commands/update.ts
144199
- async function run9(_args) {
144200
- process.stderr.write(` Checking for updates to ${bold(PKG_NAME)}...
144201
- `);
144202
- let latest;
144368
+ } else {
144369
+ toCheck = forRegistry;
144370
+ }
144371
+ console.log();
144372
+ if (target) {
144373
+ console.log(bold(` Checking ${cyan(target)}...`));
144374
+ } else {
144375
+ console.log(bold(" Checking for updates..."));
144376
+ }
144377
+ console.log();
144378
+ let updateResult;
144203
144379
  try {
144204
- latest = await fetchLatestVersion();
144205
- } catch {
144206
- process.stderr.write(` ${yellow("\u26A0")} Could not reach npm registry. Check your network and try again.
144207
- `);
144380
+ updateResult = await checkUpdates(
144381
+ toCheck.map((e) => ({ slug: e.slug, version: e.version })),
144382
+ registry2
144383
+ );
144384
+ } catch (err) {
144385
+ console.error(
144386
+ red("\u2717") + ` ${err instanceof RegistryError ? err.message : err.message}`
144387
+ );
144208
144388
  process.exit(1);
144209
144389
  }
144210
- if (!semverGt(latest, VERSION)) {
144211
- process.stderr.write(` ${green("\u2713")} Already up to date (${cyan(VERSION)})
144212
- `);
144390
+ const { updates, up_to_date, deprecated } = updateResult;
144391
+ const colWidth = Math.max(
144392
+ ...[...updates, ...up_to_date, ...deprecated].map((u) => {
144393
+ const entry = toCheck.find((e) => e.slug === u.slug);
144394
+ return entry ? compoundId2(entry).length : 0;
144395
+ }),
144396
+ 12
144397
+ );
144398
+ for (const u of up_to_date) {
144399
+ const entry = toCheck.find((e) => e.slug === u.slug);
144400
+ const id = entry ? compoundId2(entry) : u.slug;
144401
+ console.log(` ${dim(id.padEnd(colWidth))} ${dim(`v${u.version}`)} ${dim("up to date")}`);
144402
+ }
144403
+ for (const u of updates) {
144404
+ const entry = toCheck.find((e) => e.slug === u.slug);
144405
+ const id = entry ? compoundId2(entry) : u.slug;
144406
+ const badge = u.breaking ? yellow(`${u.severity} \xB7 breaking`) : cyan(u.severity);
144407
+ console.log(
144408
+ ` ${bold(id.padEnd(colWidth))} ${dim(`v${u.installed_version}`)} \u2192 ${green(`v${u.latest_version}`)} [${badge}]`
144409
+ );
144410
+ }
144411
+ for (const d of deprecated) {
144412
+ const entry = toCheck.find((e) => e.slug === d.slug);
144413
+ const id = entry ? compoundId2(entry) : d.slug;
144414
+ const note = d.replacement ? ` \u2192 use ${cyan(d.replacement)}` : "";
144415
+ console.log(` ${yellow(id.padEnd(colWidth))} ${dim(`v${d.installed_version}`)} ${yellow("deprecated")}${note}`);
144416
+ }
144417
+ console.log();
144418
+ if (updates.length === 0) {
144419
+ console.log(green("\u2713") + (target ? ` ${cyan(target)} is up to date.` : " All configs are up to date."));
144420
+ if (deprecated.length > 0) {
144421
+ console.log(yellow("\u26A0") + ` ${deprecated.length} deprecated \u2014 consider replacing them.`);
144422
+ }
144423
+ console.log();
144213
144424
  return;
144214
144425
  }
144215
- process.stderr.write(` ${bold(VERSION)} \u2192 ${bold(latest)}
144216
- `);
144217
- process.stderr.write(` Running: npm install -g ${PKG_NAME}@latest
144218
-
144219
- `);
144220
- const result = spawnSync("npm", ["install", "-g", `${PKG_NAME}@latest`], {
144221
- stdio: "inherit",
144222
- shell: true
144223
- });
144224
- if (result.status !== 0) {
144225
- process.stderr.write(
144226
- `
144227
- Update failed. You can update manually:
144228
- npm install -g ${PKG_NAME}@latest
144229
- `
144230
- );
144231
- process.exit(result.status ?? 1);
144426
+ const noun = updates.length === 1 ? "config" : "configs";
144427
+ console.log(bold(` Updating ${updates.length} ${noun}...`));
144428
+ console.log();
144429
+ const entryBySlug = new Map(toCheck.map((e) => [e.slug, e]));
144430
+ let successCount = 0;
144431
+ let failCount = 0;
144432
+ for (const u of updates) {
144433
+ const entry = entryBySlug.get(u.slug);
144434
+ if (!entry) continue;
144435
+ const id = compoundId2(entry);
144436
+ process.stdout.write(` ${bold(id.padEnd(colWidth))} Downloading... `);
144437
+ try {
144438
+ const result = await downloadAndInstall(entry, u.latest_version, configDir);
144439
+ console.log(green("done") + ` ${dim(`${result.from} \u2192 ${result.to}`)}`);
144440
+ successCount++;
144441
+ } catch (err) {
144442
+ console.log(red("failed"));
144443
+ const msg = err instanceof RegistryError ? err.message : err.message;
144444
+ console.error(` ${"".padEnd(colWidth)} ${red("\u2717")} ${msg}`);
144445
+ failCount++;
144446
+ }
144232
144447
  }
144233
- process.stderr.write(`
144234
- ${green("\u2713")} Updated to ${bold(latest)}
144235
- `);
144448
+ console.log();
144449
+ if (failCount === 0) {
144450
+ const upToDateNote = up_to_date.length > 0 ? ` ${dim(`${up_to_date.length} already up to date.`)}` : "";
144451
+ console.log(green("\u2713") + ` ${successCount} ${noun} updated.${upToDateNote}`);
144452
+ } else if (successCount > 0) {
144453
+ console.log(yellow("\u26A0") + ` ${successCount} updated, ${failCount} failed.`);
144454
+ } else {
144455
+ console.log(red("\u2717") + ` All updates failed.`);
144456
+ process.exit(1);
144457
+ }
144458
+ console.log(dim(" Restart or reload heku to apply changes."));
144459
+ console.log();
144236
144460
  }
144237
144461
 
144238
144462
  // src/cli.ts
144239
144463
  var args = process.argv.slice(2);
144240
144464
  var command = args[0] ?? "start";
144241
- if (command !== "update") {
144242
- checkForUpdate();
144243
- }
144244
144465
  switch (command) {
144245
144466
  case "start":
144246
144467
  await run(args.slice(1));
@@ -144296,11 +144517,12 @@ function printUsage() {
144296
144517
  heku auth setup [service] Interactive credential setup wizard
144297
144518
  heku install <target> Install a config from the registry
144298
144519
  heku uninstall <target> Remove an installed registry config
144520
+ heku update Update all installed configs to latest versions
144521
+ heku update <config> Update a specific config (e.g. github-http or @ns/github:http)
144299
144522
  heku login Log in to the mcp.rtl.space registry
144300
144523
  heku logout Log out of the registry
144301
144524
  heku publish [file] Publish a config to the registry
144302
144525
  heku fork <namespace/slug> Fork a registry config into your namespace
144303
- heku update Update heku to the latest version
144304
144526
  heku help Show this message
144305
144527
 
144306
144528
  HTTP mode: