@girardmedia/bootspring 2.7.0 → 3.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.
package/dist/cli/index.js CHANGED
@@ -31,10 +31,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32
32
  mod
33
33
  ));
34
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
34
35
 
35
- // ../../node_modules/.pnpm/tsup@8.5.1_jiti@1.21.7_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
36
+ // ../../node_modules/.pnpm/tsup@8.5.1_jiti@1.21.7_postcss@8.5.14_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
36
37
  var init_cjs_shims = __esm({
37
- "../../node_modules/.pnpm/tsup@8.5.1_jiti@1.21.7_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js"() {
38
+ "../../node_modules/.pnpm/tsup@8.5.1_jiti@1.21.7_postcss@8.5.14_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js"() {
38
39
  "use strict";
39
40
  }
40
41
  });
@@ -3385,7 +3386,7 @@ var init_release = __esm({
3385
3386
  "../../packages/shared/src/release.ts"() {
3386
3387
  "use strict";
3387
3388
  init_cjs_shims();
3388
- BOOTSPRING_VERSION = "2.7.0";
3389
+ BOOTSPRING_VERSION = "3.1.0";
3389
3390
  BOOTSPRING_PACKAGE_NAME = "@girardmedia/bootspring";
3390
3391
  }
3391
3392
  });
@@ -32898,13 +32899,16 @@ var require_data = __commonJS({
32898
32899
  }
32899
32900
  });
32900
32901
 
32901
- // ../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/utils.js
32902
+ // ../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js
32902
32903
  var require_utils = __commonJS({
32903
- "../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/utils.js"(exports2, module2) {
32904
+ "../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js"(exports2, module2) {
32904
32905
  "use strict";
32905
32906
  init_cjs_shims();
32906
32907
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
32907
32908
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
32909
+ var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
32910
+ var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
32911
+ var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
32908
32912
  function stringArrayToHexStripped(input) {
32909
32913
  let acc = "";
32910
32914
  let code = 0;
@@ -33097,27 +33101,77 @@ var require_utils = __commonJS({
33097
33101
  }
33098
33102
  return output.join("");
33099
33103
  }
33100
- function normalizeComponentEncoding(component, esc4) {
33101
- const func = esc4 !== true ? escape : unescape;
33102
- if (component.scheme !== void 0) {
33103
- component.scheme = func(component.scheme);
33104
- }
33105
- if (component.userinfo !== void 0) {
33106
- component.userinfo = func(component.userinfo);
33107
- }
33108
- if (component.host !== void 0) {
33109
- component.host = func(component.host);
33104
+ var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
33105
+ var HOST_DELIM_RE = /[@/?#:]/g;
33106
+ var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
33107
+ function reescapeHostDelimiters(host, isIP) {
33108
+ const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
33109
+ re.lastIndex = 0;
33110
+ return host.replace(re, (ch) => HOST_DELIMS[ch]);
33111
+ }
33112
+ function normalizePercentEncoding(input, decodeUnreserved = false) {
33113
+ if (input.indexOf("%") === -1) {
33114
+ return input;
33110
33115
  }
33111
- if (component.path !== void 0) {
33112
- component.path = func(component.path);
33116
+ let output = "";
33117
+ for (let i = 0; i < input.length; i++) {
33118
+ if (input[i] === "%" && i + 2 < input.length) {
33119
+ const hex3 = input.slice(i + 1, i + 3);
33120
+ if (isHexPair(hex3)) {
33121
+ const normalizedHex = hex3.toUpperCase();
33122
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
33123
+ if (decodeUnreserved && isUnreserved(decoded)) {
33124
+ output += decoded;
33125
+ } else {
33126
+ output += "%" + normalizedHex;
33127
+ }
33128
+ i += 2;
33129
+ continue;
33130
+ }
33131
+ }
33132
+ output += input[i];
33113
33133
  }
33114
- if (component.query !== void 0) {
33115
- component.query = func(component.query);
33134
+ return output;
33135
+ }
33136
+ function normalizePathEncoding(input) {
33137
+ let output = "";
33138
+ for (let i = 0; i < input.length; i++) {
33139
+ if (input[i] === "%" && i + 2 < input.length) {
33140
+ const hex3 = input.slice(i + 1, i + 3);
33141
+ if (isHexPair(hex3)) {
33142
+ const normalizedHex = hex3.toUpperCase();
33143
+ const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
33144
+ if (decoded !== "." && isUnreserved(decoded)) {
33145
+ output += decoded;
33146
+ } else {
33147
+ output += "%" + normalizedHex;
33148
+ }
33149
+ i += 2;
33150
+ continue;
33151
+ }
33152
+ }
33153
+ if (isPathCharacter(input[i])) {
33154
+ output += input[i];
33155
+ } else {
33156
+ output += escape(input[i]);
33157
+ }
33116
33158
  }
33117
- if (component.fragment !== void 0) {
33118
- component.fragment = func(component.fragment);
33159
+ return output;
33160
+ }
33161
+ function escapePreservingEscapes(input) {
33162
+ let output = "";
33163
+ for (let i = 0; i < input.length; i++) {
33164
+ if (input[i] === "%" && i + 2 < input.length) {
33165
+ const hex3 = input.slice(i + 1, i + 3);
33166
+ if (isHexPair(hex3)) {
33167
+ output += "%" + hex3.toUpperCase();
33168
+ i += 2;
33169
+ continue;
33170
+ }
33171
+ }
33172
+ output += escape(input[i]);
33119
33173
  }
33120
- return component;
33174
+ return output;
33121
33175
  }
33122
33176
  function recomposeAuthority(component) {
33123
33177
  const uriTokens = [];
@@ -33132,7 +33186,7 @@ var require_utils = __commonJS({
33132
33186
  if (ipV6res.isIPV6 === true) {
33133
33187
  host = `[${ipV6res.escapedHost}]`;
33134
33188
  } else {
33135
- host = component.host;
33189
+ host = reescapeHostDelimiters(host, false);
33136
33190
  }
33137
33191
  }
33138
33192
  uriTokens.push(host);
@@ -33146,7 +33200,10 @@ var require_utils = __commonJS({
33146
33200
  module2.exports = {
33147
33201
  nonSimpleDomain,
33148
33202
  recomposeAuthority,
33149
- normalizeComponentEncoding,
33203
+ reescapeHostDelimiters,
33204
+ normalizePercentEncoding,
33205
+ normalizePathEncoding,
33206
+ escapePreservingEscapes,
33150
33207
  removeDotSegments,
33151
33208
  isIPv4,
33152
33209
  isUUID,
@@ -33156,9 +33213,9 @@ var require_utils = __commonJS({
33156
33213
  }
33157
33214
  });
33158
33215
 
33159
- // ../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/schemes.js
33216
+ // ../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js
33160
33217
  var require_schemes = __commonJS({
33161
- "../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/lib/schemes.js"(exports2, module2) {
33218
+ "../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js"(exports2, module2) {
33162
33219
  "use strict";
33163
33220
  init_cjs_shims();
33164
33221
  var { isUUID } = require_utils();
@@ -33367,17 +33424,17 @@ var require_schemes = __commonJS({
33367
33424
  }
33368
33425
  });
33369
33426
 
33370
- // ../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/index.js
33427
+ // ../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js
33371
33428
  var require_fast_uri = __commonJS({
33372
- "../../node_modules/.pnpm/fast-uri@3.1.0/node_modules/fast-uri/index.js"(exports2, module2) {
33429
+ "../../node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js"(exports2, module2) {
33373
33430
  "use strict";
33374
33431
  init_cjs_shims();
33375
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
33432
+ var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
33376
33433
  var { SCHEMES, getSchemeHandler } = require_schemes();
33377
33434
  function normalize2(uri, options) {
33378
33435
  if (typeof uri === "string") {
33379
33436
  uri = /** @type {T} */
33380
- serialize(parse7(uri, options), options);
33437
+ normalizeString(uri, options);
33381
33438
  } else if (typeof uri === "object") {
33382
33439
  uri = /** @type {T} */
33383
33440
  parse7(serialize(uri, options), options);
@@ -33444,19 +33501,9 @@ var require_fast_uri = __commonJS({
33444
33501
  return target;
33445
33502
  }
33446
33503
  function equal(uriA, uriB, options) {
33447
- if (typeof uriA === "string") {
33448
- uriA = unescape(uriA);
33449
- uriA = serialize(normalizeComponentEncoding(parse7(uriA, options), true), { ...options, skipEscape: true });
33450
- } else if (typeof uriA === "object") {
33451
- uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
33452
- }
33453
- if (typeof uriB === "string") {
33454
- uriB = unescape(uriB);
33455
- uriB = serialize(normalizeComponentEncoding(parse7(uriB, options), true), { ...options, skipEscape: true });
33456
- } else if (typeof uriB === "object") {
33457
- uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
33458
- }
33459
- return uriA.toLowerCase() === uriB.toLowerCase();
33504
+ const normalizedA = normalizeComparableURI(uriA, options);
33505
+ const normalizedB = normalizeComparableURI(uriB, options);
33506
+ return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
33460
33507
  }
33461
33508
  function serialize(cmpts, opts) {
33462
33509
  const component = {
@@ -33481,12 +33528,12 @@ var require_fast_uri = __commonJS({
33481
33528
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
33482
33529
  if (component.path !== void 0) {
33483
33530
  if (!options.skipEscape) {
33484
- component.path = escape(component.path);
33531
+ component.path = escapePreservingEscapes(component.path);
33485
33532
  if (component.scheme !== void 0) {
33486
33533
  component.path = component.path.split("%3A").join(":");
33487
33534
  }
33488
33535
  } else {
33489
- component.path = unescape(component.path);
33536
+ component.path = normalizePercentEncoding(component.path);
33490
33537
  }
33491
33538
  }
33492
33539
  if (options.reference !== "suffix" && component.scheme) {
@@ -33521,7 +33568,16 @@ var require_fast_uri = __commonJS({
33521
33568
  return uriTokens.join("");
33522
33569
  }
33523
33570
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
33524
- function parse7(uri, opts) {
33571
+ function getParseError(parsed, matches) {
33572
+ if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
33573
+ return 'URI path must start with "/" when authority is present.';
33574
+ }
33575
+ if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
33576
+ return "URI port is malformed.";
33577
+ }
33578
+ return void 0;
33579
+ }
33580
+ function parseWithStatus(uri, opts) {
33525
33581
  const options = Object.assign({}, opts);
33526
33582
  const parsed = {
33527
33583
  scheme: void 0,
@@ -33532,6 +33588,7 @@ var require_fast_uri = __commonJS({
33532
33588
  query: void 0,
33533
33589
  fragment: void 0
33534
33590
  };
33591
+ let malformedAuthorityOrPort = false;
33535
33592
  let isIP = false;
33536
33593
  if (options.reference === "suffix") {
33537
33594
  if (options.scheme) {
@@ -33552,6 +33609,11 @@ var require_fast_uri = __commonJS({
33552
33609
  if (isNaN(parsed.port)) {
33553
33610
  parsed.port = matches[5];
33554
33611
  }
33612
+ const parseError = getParseError(parsed, matches);
33613
+ if (parseError !== void 0) {
33614
+ parsed.error = parsed.error || parseError;
33615
+ malformedAuthorityOrPort = true;
33616
+ }
33555
33617
  if (parsed.host) {
33556
33618
  const ipv4result = isIPv4(parsed.host);
33557
33619
  if (ipv4result === false) {
@@ -33590,14 +33652,18 @@ var require_fast_uri = __commonJS({
33590
33652
  parsed.scheme = unescape(parsed.scheme);
33591
33653
  }
33592
33654
  if (parsed.host !== void 0) {
33593
- parsed.host = unescape(parsed.host);
33655
+ parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
33594
33656
  }
33595
33657
  }
33596
33658
  if (parsed.path) {
33597
- parsed.path = escape(unescape(parsed.path));
33659
+ parsed.path = normalizePathEncoding(parsed.path);
33598
33660
  }
33599
33661
  if (parsed.fragment) {
33600
- parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
33662
+ try {
33663
+ parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
33664
+ } catch {
33665
+ parsed.error = parsed.error || "URI malformed";
33666
+ }
33601
33667
  }
33602
33668
  }
33603
33669
  if (schemeHandler && schemeHandler.parse) {
@@ -33606,7 +33672,29 @@ var require_fast_uri = __commonJS({
33606
33672
  } else {
33607
33673
  parsed.error = parsed.error || "URI can not be parsed.";
33608
33674
  }
33609
- return parsed;
33675
+ return { parsed, malformedAuthorityOrPort };
33676
+ }
33677
+ function parse7(uri, opts) {
33678
+ return parseWithStatus(uri, opts).parsed;
33679
+ }
33680
+ function normalizeString(uri, opts) {
33681
+ return normalizeStringWithStatus(uri, opts).normalized;
33682
+ }
33683
+ function normalizeStringWithStatus(uri, opts) {
33684
+ const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
33685
+ return {
33686
+ normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
33687
+ malformedAuthorityOrPort
33688
+ };
33689
+ }
33690
+ function normalizeComparableURI(uri, opts) {
33691
+ if (typeof uri === "string") {
33692
+ const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
33693
+ return malformedAuthorityOrPort ? void 0 : normalized;
33694
+ }
33695
+ if (typeof uri === "object") {
33696
+ return serialize(uri, opts);
33697
+ }
33610
33698
  }
33611
33699
  var fastUri = {
33612
33700
  SCHEMES,
@@ -38412,7 +38500,7 @@ var require_main = __commonJS({
38412
38500
  }
38413
38501
  return to;
38414
38502
  };
38415
- var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
38503
+ var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
38416
38504
  var node_exports = {};
38417
38505
  __export2(node_exports, {
38418
38506
  analyzeMetafile: () => analyzeMetafile,
@@ -38429,7 +38517,7 @@ var require_main = __commonJS({
38429
38517
  transformSync: () => transformSync,
38430
38518
  version: () => version3
38431
38519
  });
38432
- module2.exports = __toCommonJS(node_exports);
38520
+ module2.exports = __toCommonJS2(node_exports);
38433
38521
  function encodePacket(packet) {
38434
38522
  let visit = (value) => {
38435
38523
  if (value === null) {
@@ -39210,7 +39298,7 @@ is not a problem with esbuild. You need to fix your environment instead.
39210
39298
  function buildOrContextImpl(callName, buildKey, sendRequest, sendResponse, refs, streamIn, requestCallbacks, options, isTTY2, defaultWD2, callback) {
39211
39299
  const details = createObjectStash();
39212
39300
  const isContext = callName === "context";
39213
- const handleError = (e, pluginName) => {
39301
+ const handleError2 = (e, pluginName) => {
39214
39302
  const flags = [];
39215
39303
  try {
39216
39304
  pushLogFlags(flags, options, {}, isTTY2, buildLogLevelDefault);
@@ -39226,12 +39314,12 @@ is not a problem with esbuild. You need to fix your environment instead.
39226
39314
  if (typeof options === "object") {
39227
39315
  const value = options.plugins;
39228
39316
  if (value !== void 0) {
39229
- if (!Array.isArray(value)) return handleError(new Error(`"plugins" must be an array`), "");
39317
+ if (!Array.isArray(value)) return handleError2(new Error(`"plugins" must be an array`), "");
39230
39318
  plugins = value;
39231
39319
  }
39232
39320
  }
39233
39321
  if (plugins && plugins.length > 0) {
39234
- if (streamIn.isSync) return handleError(new Error("Cannot use plugins in synchronous API calls"), "");
39322
+ if (streamIn.isSync) return handleError2(new Error("Cannot use plugins in synchronous API calls"), "");
39235
39323
  handlePlugins(
39236
39324
  buildKey,
39237
39325
  sendRequest,
@@ -39244,14 +39332,14 @@ is not a problem with esbuild. You need to fix your environment instead.
39244
39332
  details
39245
39333
  ).then(
39246
39334
  (result) => {
39247
- if (!result.ok) return handleError(result.error, result.pluginName);
39335
+ if (!result.ok) return handleError2(result.error, result.pluginName);
39248
39336
  try {
39249
39337
  buildOrContextContinue(result.requestPlugins, result.runOnEndCallbacks, result.scheduleOnDisposeCallbacks);
39250
39338
  } catch (e) {
39251
- handleError(e, "");
39339
+ handleError2(e, "");
39252
39340
  }
39253
39341
  },
39254
- (e) => handleError(e, "")
39342
+ (e) => handleError2(e, "")
39255
39343
  );
39256
39344
  return;
39257
39345
  }
@@ -39259,7 +39347,7 @@ is not a problem with esbuild. You need to fix your environment instead.
39259
39347
  buildOrContextContinue(null, (result, done) => done([], []), () => {
39260
39348
  });
39261
39349
  } catch (e) {
39262
- handleError(e, "");
39350
+ handleError2(e, "");
39263
39351
  }
39264
39352
  function buildOrContextContinue(requestPlugins, runOnEndCallbacks, scheduleOnDisposeCallbacks) {
39265
39353
  const writeDefault = streamIn.hasFS;
@@ -45895,6 +45983,317 @@ ${"=".repeat(50)}`);
45895
45983
  }
45896
45984
  });
45897
45985
 
45986
+ // ../../packages/mcp/src/swarm-tools.ts
45987
+ function errorResult(message) {
45988
+ return {
45989
+ content: [{ type: "text", text: `Error: ${message}` }],
45990
+ isError: true
45991
+ };
45992
+ }
45993
+ function registerSwarmTools() {
45994
+ registerTool(swarmDefinition, swarmHandler);
45995
+ registerTool(memoryDefinition, memoryHandler);
45996
+ registerTool(planDefinition, planHandler);
45997
+ }
45998
+ var swarmDefinition, swarmHandler, memoryDefinition, memoryHandler, planDefinition, planHandler, SWARM_TOOLS;
45999
+ var init_swarm_tools = __esm({
46000
+ "../../packages/mcp/src/swarm-tools.ts"() {
46001
+ "use strict";
46002
+ init_cjs_shims();
46003
+ init_registry();
46004
+ swarmDefinition = {
46005
+ name: "bootspring_swarm",
46006
+ description: "Multi-agent swarm orchestration \u2014 start swarms, spawn agents, submit tasks, run consensus votes, and change topologies (hierarchical, mesh, ring, star, adaptive). Agents collaborate through shared state and self-organize based on workload.",
46007
+ inputSchema: {
46008
+ type: "object",
46009
+ properties: {
46010
+ action: {
46011
+ type: "string",
46012
+ enum: ["start", "stop", "status", "spawn", "agents", "submit", "batch", "consensus", "topology"],
46013
+ description: "Swarm action to perform"
46014
+ },
46015
+ topology: {
46016
+ type: "string",
46017
+ enum: ["hierarchical", "mesh", "ring", "star", "adaptive"],
46018
+ description: "Swarm topology (for start/topology actions)"
46019
+ },
46020
+ role: {
46021
+ type: "string",
46022
+ enum: ["queen", "worker", "specialist", "reviewer", "monitor"],
46023
+ description: "Agent role (for spawn action)"
46024
+ },
46025
+ capabilities: {
46026
+ type: "array",
46027
+ items: { type: "string" },
46028
+ description: "Agent capabilities (for spawn action)"
46029
+ },
46030
+ taskType: {
46031
+ type: "string",
46032
+ description: "Task type (for submit action)"
46033
+ },
46034
+ taskDescription: {
46035
+ type: "string",
46036
+ description: "Task description (for submit action)"
46037
+ },
46038
+ priority: {
46039
+ type: "string",
46040
+ enum: ["critical", "high", "normal", "low"],
46041
+ description: "Task priority (for submit action)"
46042
+ },
46043
+ question: {
46044
+ type: "string",
46045
+ description: "Question for consensus vote"
46046
+ },
46047
+ options: {
46048
+ type: "array",
46049
+ items: { type: "string" },
46050
+ description: "Vote options for consensus"
46051
+ }
46052
+ },
46053
+ required: ["action"]
46054
+ }
46055
+ };
46056
+ swarmHandler = async (args) => {
46057
+ const action = String(args.action || "");
46058
+ try {
46059
+ const { api } = (init_src2(), __toCommonJS(src_exports2));
46060
+ let result;
46061
+ switch (action) {
46062
+ case "start":
46063
+ result = await api.request("POST", "/swarm/start", {
46064
+ topology: args.topology || "hierarchical"
46065
+ });
46066
+ break;
46067
+ case "stop":
46068
+ result = await api.request("POST", "/swarm/stop");
46069
+ break;
46070
+ case "status":
46071
+ result = await api.request("GET", "/swarm/status");
46072
+ break;
46073
+ case "spawn":
46074
+ if (!args.role) return errorResult("role is required for spawn");
46075
+ result = await api.request("POST", "/swarm/agents", {
46076
+ role: args.role,
46077
+ capabilities: args.capabilities || ["general"]
46078
+ });
46079
+ break;
46080
+ case "agents":
46081
+ result = await api.request("GET", "/swarm/agents");
46082
+ break;
46083
+ case "submit":
46084
+ if (!args.taskType || !args.taskDescription) {
46085
+ return errorResult("taskType and taskDescription are required for submit");
46086
+ }
46087
+ result = await api.request("POST", "/swarm/tasks", {
46088
+ type: args.taskType,
46089
+ description: args.taskDescription,
46090
+ input: {},
46091
+ priority: args.priority || "normal"
46092
+ });
46093
+ break;
46094
+ case "consensus":
46095
+ if (!args.question || !args.options) {
46096
+ return errorResult("question and options are required for consensus");
46097
+ }
46098
+ result = await api.request("POST", "/swarm/consensus", {
46099
+ question: args.question,
46100
+ options: args.options
46101
+ });
46102
+ break;
46103
+ case "topology":
46104
+ if (args.topology) {
46105
+ result = await api.request("POST", "/swarm/topology", { topology: args.topology });
46106
+ } else {
46107
+ result = await api.request("GET", "/swarm/topology");
46108
+ }
46109
+ break;
46110
+ default:
46111
+ return errorResult(`Unknown action: ${action}`);
46112
+ }
46113
+ return {
46114
+ content: [{
46115
+ type: "text",
46116
+ text: `Swarm ${action} result:
46117
+ ${JSON.stringify(result, null, 2)}`
46118
+ }]
46119
+ };
46120
+ } catch (err) {
46121
+ return errorResult(err instanceof Error ? err.message : String(err));
46122
+ }
46123
+ };
46124
+ memoryDefinition = {
46125
+ name: "bootspring_memory",
46126
+ description: "Vector memory for AI agents \u2014 store decisions, patterns, and trajectories. Search by semantic similarity using HNSW index. Agents learn from past successes.",
46127
+ inputSchema: {
46128
+ type: "object",
46129
+ properties: {
46130
+ action: {
46131
+ type: "string",
46132
+ enum: ["search", "store", "trajectory", "stats", "forget"],
46133
+ description: "Memory action to perform"
46134
+ },
46135
+ query: {
46136
+ type: "string",
46137
+ description: "Search query (for search action)"
46138
+ },
46139
+ content: {
46140
+ type: "string",
46141
+ description: "Content to store (for store action)"
46142
+ },
46143
+ type: {
46144
+ type: "string",
46145
+ enum: ["decision", "pattern", "error", "solution", "context", "preference", "trajectory"],
46146
+ description: "Memory entry type"
46147
+ },
46148
+ goal: {
46149
+ type: "string",
46150
+ description: "Goal (for trajectory action)"
46151
+ },
46152
+ steps: {
46153
+ type: "array",
46154
+ items: { type: "string" },
46155
+ description: "Steps taken (for trajectory action)"
46156
+ },
46157
+ outcome: {
46158
+ type: "string",
46159
+ enum: ["success", "partial", "failure"],
46160
+ description: "Trajectory outcome"
46161
+ },
46162
+ id: {
46163
+ type: "string",
46164
+ description: "Entry ID (for forget action)"
46165
+ },
46166
+ limit: {
46167
+ type: "number",
46168
+ description: "Max results for search (default 10)"
46169
+ }
46170
+ },
46171
+ required: ["action"]
46172
+ }
46173
+ };
46174
+ memoryHandler = async (args) => {
46175
+ const action = String(args.action || "");
46176
+ try {
46177
+ const { api } = (init_src2(), __toCommonJS(src_exports2));
46178
+ let result;
46179
+ switch (action) {
46180
+ case "search":
46181
+ if (!args.query) return errorResult("query is required for search");
46182
+ result = await api.request("POST", "/swarm/memory/search", {
46183
+ query: args.query,
46184
+ limit: args.limit || 10,
46185
+ type: args.type
46186
+ });
46187
+ break;
46188
+ case "store":
46189
+ if (!args.content || !args.type) return errorResult("content and type are required for store");
46190
+ result = await api.request("POST", "/swarm/memory", {
46191
+ content: args.content,
46192
+ type: args.type,
46193
+ sessionId: `mcp-${Date.now()}`
46194
+ });
46195
+ break;
46196
+ case "trajectory":
46197
+ if (!args.goal || !args.steps || !args.outcome) {
46198
+ return errorResult("goal, steps, and outcome are required for trajectory");
46199
+ }
46200
+ result = await api.request("POST", "/swarm/memory/trajectory", {
46201
+ goal: args.goal,
46202
+ steps: args.steps,
46203
+ sessionId: `mcp-${Date.now()}`,
46204
+ outcome: args.outcome
46205
+ });
46206
+ break;
46207
+ case "stats":
46208
+ result = await api.request("GET", "/swarm/memory/stats");
46209
+ break;
46210
+ case "forget":
46211
+ if (!args.id) return errorResult("id is required for forget");
46212
+ result = await api.request("DELETE", `/swarm/memory/${args.id}`);
46213
+ break;
46214
+ default:
46215
+ return errorResult(`Unknown action: ${action}`);
46216
+ }
46217
+ return {
46218
+ content: [{
46219
+ type: "text",
46220
+ text: `Memory ${action} result:
46221
+ ${JSON.stringify(result, null, 2)}`
46222
+ }]
46223
+ };
46224
+ } catch (err) {
46225
+ return errorResult(err instanceof Error ? err.message : String(err));
46226
+ }
46227
+ };
46228
+ planDefinition = {
46229
+ name: "bootspring_plan",
46230
+ description: "Goal-oriented action planning (GOAP) \u2014 decompose high-level goals into executable task DAGs with A* search. Finds optimal sequences and parallelizable groups.",
46231
+ inputSchema: {
46232
+ type: "object",
46233
+ properties: {
46234
+ action: {
46235
+ type: "string",
46236
+ enum: ["plan", "actions", "register"],
46237
+ description: "Planner action"
46238
+ },
46239
+ goal: {
46240
+ type: "string",
46241
+ description: "Goal to plan for (for plan action)"
46242
+ },
46243
+ parallel: {
46244
+ type: "boolean",
46245
+ description: "Enable parallel task groups"
46246
+ },
46247
+ currentState: {
46248
+ type: "object",
46249
+ description: "Current world state (key-value pairs)"
46250
+ },
46251
+ goalConditions: {
46252
+ type: "array",
46253
+ description: "Goal conditions [{key, operator, value}]"
46254
+ }
46255
+ },
46256
+ required: ["action"]
46257
+ }
46258
+ };
46259
+ planHandler = async (args) => {
46260
+ const action = String(args.action || "");
46261
+ try {
46262
+ const { api } = (init_src2(), __toCommonJS(src_exports2));
46263
+ let result;
46264
+ switch (action) {
46265
+ case "plan":
46266
+ if (!args.goal) return errorResult("goal is required for plan");
46267
+ result = await api.request("POST", "/swarm/plan", {
46268
+ goal: args.goal,
46269
+ currentState: args.currentState || {},
46270
+ goalConditions: args.goalConditions || [{ key: "deployed", operator: "==", value: true }],
46271
+ parallel: args.parallel ?? true
46272
+ });
46273
+ break;
46274
+ case "actions":
46275
+ result = await api.request("GET", "/swarm/plan/actions");
46276
+ break;
46277
+ case "register":
46278
+ return errorResult("Register custom actions via the API: POST /swarm/plan/actions");
46279
+ default:
46280
+ return errorResult(`Unknown action: ${action}`);
46281
+ }
46282
+ return {
46283
+ content: [{
46284
+ type: "text",
46285
+ text: `Plan ${action} result:
46286
+ ${JSON.stringify(result, null, 2)}`
46287
+ }]
46288
+ };
46289
+ } catch (err) {
46290
+ return errorResult(err instanceof Error ? err.message : String(err));
46291
+ }
46292
+ };
46293
+ SWARM_TOOLS = [swarmDefinition, memoryDefinition, planDefinition];
46294
+ }
46295
+ });
46296
+
45898
46297
  // ../../packages/mcp/src/index.ts
45899
46298
  var src_exports3 = {};
45900
46299
  __export(src_exports3, {
@@ -45912,6 +46311,7 @@ __export(src_exports3, {
45912
46311
  QUALITY_INTELLIGENCE_TOOLS: () => QUALITY_INTELLIGENCE_TOOLS,
45913
46312
  RBAC_TOOLS: () => RBAC_TOOLS,
45914
46313
  RELEASE_TOOLS: () => RELEASE_TOOLS,
46314
+ SWARM_TOOLS: () => SWARM_TOOLS,
45915
46315
  SYNC_TOOLS: () => SYNC_TOOLS,
45916
46316
  agentDetails: () => agentDetails,
45917
46317
  assistResponse: () => assistResponse,
@@ -45953,6 +46353,7 @@ __export(src_exports3, {
45953
46353
  registerRbacTools: () => registerRbacTools,
45954
46354
  registerReleaseTools: () => registerReleaseTools,
45955
46355
  registerResource: () => registerResource,
46356
+ registerSwarmTools: () => registerSwarmTools,
45956
46357
  registerSyncTools: () => registerSyncTools,
45957
46358
  registerTool: () => registerTool,
45958
46359
  resolveCompatibilityRegistry: () => resolveCompatibilityRegistry,
@@ -45988,6 +46389,7 @@ var init_src3 = __esm({
45988
46389
  init_observer_tools();
45989
46390
  init_autopilot_tools();
45990
46391
  init_brain_tools();
46392
+ init_swarm_tools();
45991
46393
  }
45992
46394
  });
45993
46395
 
@@ -56629,7 +57031,7 @@ function registerBuildCommand(program3) {
56629
57031
  print.info(`Complexity: ${next.complexity ?? "Unknown"}`);
56630
57032
  if (current) print.info(`Status: ${next.status}`);
56631
57033
  });
56632
- build.command("done").alias("complete").description("Mark the current task as done (trusts caller \u2014 does not verify execution)").action(() => {
57034
+ build.command("done").alias("complete").description("Mark the current task as done, auto-commit, and show next task").option("--no-commit", "Skip auto-commit").action((opts) => {
56633
57035
  const state = loadBuildStateWithAutoSync();
56634
57036
  if (!state) {
56635
57037
  print.error("No build state found");
@@ -56643,15 +57045,54 @@ function registerBuildCommand(program3) {
56643
57045
  return;
56644
57046
  }
56645
57047
  const currentId = queue[idx].id;
57048
+ const currentTitle = queue[idx].title;
57049
+ if (opts.commit !== false) {
57050
+ try {
57051
+ const { execSync: execSync15 } = require("child_process");
57052
+ const cwd = process.cwd();
57053
+ const status = execSync15("git status --porcelain", { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
57054
+ if (status) {
57055
+ execSync15("git add -A", { cwd, stdio: ["ignore", "ignore", "ignore"] });
57056
+ const msg = `feat(${currentId}): ${currentTitle}`;
57057
+ execSync15(`git commit -m ${JSON.stringify(msg)}`, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
57058
+ print.success(`Committed: ${msg}`);
57059
+ }
57060
+ } catch {
57061
+ }
57062
+ }
56646
57063
  queue[idx].status = "completed";
56647
57064
  if (state.loopSession) {
56648
57065
  state.loopSession.currentIteration = (state.loopSession.currentIteration ?? 0) + 1;
56649
57066
  }
56650
57067
  saveBuildState(state);
56651
- const nextTask = queue.find((t) => t.status === "pending");
57068
+ const nextTask = (() => {
57069
+ for (const task of queue) {
57070
+ if (task.status !== "pending") continue;
57071
+ if (task.dependencies?.length) {
57072
+ const allDone = task.dependencies.every((depId) => {
57073
+ const dep = queue.find((t) => t.id === depId);
57074
+ return dep && dep.status === "completed";
57075
+ });
57076
+ if (!allDone) continue;
57077
+ }
57078
+ return task;
57079
+ }
57080
+ return null;
57081
+ })();
56652
57082
  print.success(`Task ${currentId} marked as done`);
56653
57083
  if (nextTask) {
56654
- print.info(`Next: ${nextTask.id} - ${nextTask.title}`);
57084
+ console.log("");
57085
+ print.header("Next Task");
57086
+ print.info(`ID: ${nextTask.id}`);
57087
+ print.info(`Title: ${nextTask.title}`);
57088
+ if (nextTask.phase) print.info(`Phase: ${nextTask.phase}`);
57089
+ if (nextTask.description) print.info(`Description: ${nextTask.description}`);
57090
+ if (nextTask.acceptanceCriteria && nextTask.acceptanceCriteria.length > 0) {
57091
+ print.info("Acceptance criteria:");
57092
+ for (const ac of nextTask.acceptanceCriteria) {
57093
+ console.log(` [ ] ${ac}`);
57094
+ }
57095
+ }
56655
57096
  } else {
56656
57097
  print.success("No more pending tasks!");
56657
57098
  }
@@ -57537,6 +57978,71 @@ ${supplementaryContent}
57537
57978
  print.dim(`${snapshot.completedCount} completed, ${snapshot.pendingCount} pending`);
57538
57979
  }
57539
57980
  });
57981
+ build.command("handoff").description("Save or load session handoff state for cross-session continuity").option("--save", "Save current session state").option("--notes <notes>", "Notes for the next session").option("--json", "Output as JSON").action((opts) => {
57982
+ const handoffPath = path52.join(process.cwd(), "planning", ".handoff.json");
57983
+ if (opts.save) {
57984
+ const state = loadBuildStateWithAutoSync(true);
57985
+ const queue = state?.implementationQueue ?? [];
57986
+ const inProgress = queue.find((t) => t.status === "in_progress");
57987
+ const lastCompleted = [...queue].reverse().find((t) => t.status === "completed");
57988
+ let filesModified = [];
57989
+ try {
57990
+ const { execSync: execSync15 } = require("child_process");
57991
+ const gitDiff = execSync15("git diff --name-only HEAD~1 2>/dev/null || true", { encoding: "utf8" }).trim();
57992
+ if (gitDiff) filesModified = gitDiff.split("\n").filter(Boolean);
57993
+ } catch {
57994
+ }
57995
+ const handoff = {
57996
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
57997
+ lastTaskId: lastCompleted?.id ?? null,
57998
+ inProgressTask: inProgress?.id ?? null,
57999
+ inProgressTitle: inProgress?.title ?? null,
58000
+ filesModified,
58001
+ notes: opts.notes ?? "",
58002
+ blockers: [],
58003
+ progress: {
58004
+ completed: queue.filter((t) => t.status === "completed").length,
58005
+ pending: queue.filter((t) => t.status === "pending").length,
58006
+ total: queue.length
58007
+ }
58008
+ };
58009
+ const dir = path52.dirname(handoffPath);
58010
+ if (!fs51.existsSync(dir)) fs51.mkdirSync(dir, { recursive: true });
58011
+ fs51.writeFileSync(handoffPath, JSON.stringify(handoff, null, 2));
58012
+ if (opts.json) {
58013
+ console.log(JSON.stringify({ saved: true, handoff }));
58014
+ } else {
58015
+ print.success("Session handoff saved");
58016
+ if (inProgress) print.info(`In-progress: ${inProgress.id} \u2014 ${inProgress.title}`);
58017
+ if (opts.notes) print.info(`Notes: ${opts.notes}`);
58018
+ }
58019
+ return;
58020
+ }
58021
+ if (!fs51.existsSync(handoffPath)) {
58022
+ if (opts.json) {
58023
+ console.log(JSON.stringify({ hasHandoff: false }));
58024
+ } else {
58025
+ print.info("No previous session handoff found.");
58026
+ }
58027
+ return;
58028
+ }
58029
+ try {
58030
+ const handoff = JSON.parse(fs51.readFileSync(handoffPath, "utf-8"));
58031
+ if (opts.json) {
58032
+ console.log(JSON.stringify({ hasHandoff: true, handoff }));
58033
+ } else {
58034
+ print.header("Session Handoff");
58035
+ print.info(`Saved: ${handoff.timestamp}`);
58036
+ if (handoff.inProgressTask) print.info(`In-progress: ${handoff.inProgressTask} \u2014 ${handoff.inProgressTitle ?? ""}`);
58037
+ if (handoff.lastTaskId) print.info(`Last completed: ${handoff.lastTaskId}`);
58038
+ if (handoff.notes) print.info(`Notes: ${handoff.notes}`);
58039
+ if (handoff.progress) print.info(`Progress: ${handoff.progress.completed}/${handoff.progress.total}`);
58040
+ if (handoff.filesModified?.length) print.dim(`Files: ${handoff.filesModified.slice(0, 5).join(", ")}${handoff.filesModified.length > 5 ? ` +${handoff.filesModified.length - 5} more` : ""}`);
58041
+ }
58042
+ } catch {
58043
+ print.error("Failed to read handoff file");
58044
+ }
58045
+ });
57540
58046
  build.action(() => {
57541
58047
  build.outputHelp();
57542
58048
  });
@@ -66356,7 +66862,7 @@ function drawProgressBar(progress, width = 20) {
66356
66862
  }
66357
66863
  function getWorkflowStates(projectRoot) {
66358
66864
  const workflows = {};
66359
- const names = ["onboard", "analyze", "audit", "seed", "context", "deploy", "loop", "preseed"];
66865
+ const names = ["onboard", "analyze", "audit", "seed", "context", "deploy", "loop"];
66360
66866
  for (const name of names) {
66361
66867
  const stateFile = path78.join(projectRoot, ".bootspring", name, "workflow-state.json");
66362
66868
  if (fs77.existsSync(stateFile)) {
@@ -72858,10 +73364,434 @@ function registerHarnessCommand(program3) {
72858
73364
  });
72859
73365
  }
72860
73366
 
72861
- // src/commands/geo.ts
73367
+ // src/commands/swarm.ts
72862
73368
  init_cjs_shims();
72863
73369
  init_src2();
72864
73370
  function requireAuth4() {
73371
+ if (auth_exports.isAuthenticated()) return true;
73372
+ print(`${COLORS.red}Not authenticated.${COLORS.reset} Run ${COLORS.bold}bootspring auth login${COLORS.reset} first.`);
73373
+ process.exitCode = 1;
73374
+ return false;
73375
+ }
73376
+ function handleError(error50) {
73377
+ if (error50 && typeof error50 === "object" && "response" in error50) {
73378
+ const resp = error50.response;
73379
+ if (resp?.status === 403) {
73380
+ print(`
73381
+ ${COLORS.yellow}Swarm Intelligence requires Pro tier or higher.${COLORS.reset}`);
73382
+ print(`Upgrade at: ${COLORS.cyan}https://bootspring.com/pricing${COLORS.reset}
73383
+ `);
73384
+ return;
73385
+ }
73386
+ print(`${COLORS.red}Error:${COLORS.reset} ${resp?.data?.error || resp?.data?.message || "Unknown API error"}`);
73387
+ return;
73388
+ }
73389
+ print(`${COLORS.red}Error:${COLORS.reset} ${error50 instanceof Error ? error50.message : String(error50)}`);
73390
+ }
73391
+ var TOPOLOGY_SYMBOLS = {
73392
+ hierarchical: "\u25B3",
73393
+ // △
73394
+ mesh: "\u25C6",
73395
+ // ◆
73396
+ ring: "\u25CB",
73397
+ // ○
73398
+ star: "\u2605",
73399
+ // ★
73400
+ adaptive: "\u21C4"
73401
+ // ⇄
73402
+ };
73403
+ var STATUS_COLORS = {
73404
+ idle: COLORS.green,
73405
+ busy: COLORS.cyan,
73406
+ waiting: COLORS.yellow,
73407
+ failed: COLORS.red,
73408
+ offline: COLORS.dim
73409
+ };
73410
+ function registerSwarmCommand(program3) {
73411
+ const cmd = program3.command("swarm").description("Multi-agent swarm orchestration \u2014 topology, consensus, planning");
73412
+ cmd.command("start").description("Start a new swarm").option("-t, --topology <type>", "Topology: hierarchical, mesh, ring, star, adaptive", "hierarchical").option("--max-agents <n>", "Maximum agents", "50").option("--json", "Output as JSON").action(async (opts) => {
73413
+ if (!requireAuth4()) return;
73414
+ try {
73415
+ const res = await api_client_exports.request("POST", "/swarm/start", {
73416
+ topology: opts.topology,
73417
+ maxAgents: parseInt(opts.maxAgents, 10)
73418
+ });
73419
+ if (opts.json) {
73420
+ print(JSON.stringify(res, null, 2));
73421
+ return;
73422
+ }
73423
+ const topo = opts.topology;
73424
+ const sym = TOPOLOGY_SYMBOLS[topo] || "";
73425
+ print(`
73426
+ ${COLORS.bold}${COLORS.cyan}${sym} Swarm Started${COLORS.reset}`);
73427
+ print(` Topology: ${COLORS.green}${topo}${COLORS.reset}`);
73428
+ print(` Max Agents: ${opts.maxAgents}`);
73429
+ print(` Phase: ${res.config?.phase || "running"}
73430
+ `);
73431
+ } catch (error50) {
73432
+ handleError(error50);
73433
+ }
73434
+ });
73435
+ cmd.command("stop").description("Stop the current swarm").option("--json", "Output as JSON").action(async (opts) => {
73436
+ if (!requireAuth4()) return;
73437
+ try {
73438
+ const res = await api_client_exports.request("POST", "/swarm/stop");
73439
+ if (opts.json) {
73440
+ print(JSON.stringify(res, null, 2));
73441
+ return;
73442
+ }
73443
+ print(`
73444
+ ${COLORS.bold}Swarm Stopped${COLORS.reset}`);
73445
+ if (res.metrics) {
73446
+ print(` Tasks Completed: ${COLORS.green}${res.metrics.completedTasks}${COLORS.reset}`);
73447
+ print(` Tasks Failed: ${COLORS.red}${res.metrics.failedTasks}${COLORS.reset}`);
73448
+ print(` Total Agents: ${res.metrics.totalAgents}`);
73449
+ }
73450
+ print("");
73451
+ } catch (error50) {
73452
+ handleError(error50);
73453
+ }
73454
+ });
73455
+ cmd.command("status").description("Show swarm metrics and topology").option("--json", "Output as JSON").action(async (opts) => {
73456
+ if (!requireAuth4()) return;
73457
+ try {
73458
+ const res = await api_client_exports.request("GET", "/swarm/status");
73459
+ if (opts.json) {
73460
+ print(JSON.stringify(res, null, 2));
73461
+ return;
73462
+ }
73463
+ const m = res.metrics;
73464
+ const sym = TOPOLOGY_SYMBOLS[m.topology] || "";
73465
+ print(`
73466
+ ${COLORS.bold}${COLORS.cyan}${sym} Swarm Status${COLORS.reset}`);
73467
+ print(`${"\u2500".repeat(50)}`);
73468
+ print(` Phase: ${m.phase}`);
73469
+ print(` Topology: ${COLORS.green}${m.topology}${COLORS.reset}`);
73470
+ print(` Uptime: ${Math.round(m.uptime / 1e3)}s`);
73471
+ print("");
73472
+ print(` ${COLORS.bold}Agents${COLORS.reset}`);
73473
+ print(` Total: ${m.totalAgents}`);
73474
+ print(` Active: ${COLORS.cyan}${m.activeAgents}${COLORS.reset}`);
73475
+ print(` Idle: ${COLORS.green}${m.idleAgents}${COLORS.reset}`);
73476
+ print(` Failed: ${COLORS.red}${m.failedAgents}${COLORS.reset}`);
73477
+ print("");
73478
+ print(` ${COLORS.bold}Tasks${COLORS.reset}`);
73479
+ print(` Total: ${m.totalTasks}`);
73480
+ print(` Running: ${COLORS.cyan}${m.runningTasks}${COLORS.reset}`);
73481
+ print(` Pending: ${COLORS.yellow}${m.pendingTasks}${COLORS.reset}`);
73482
+ print(` Completed: ${COLORS.green}${m.completedTasks}${COLORS.reset}`);
73483
+ print(` Failed: ${COLORS.red}${m.failedTasks}${COLORS.reset}`);
73484
+ print("");
73485
+ print(` Throughput: ${m.throughputTasksPerMin} tasks/min`);
73486
+ print(` Avg Time: ${m.avgTaskDurationMs}ms`);
73487
+ if (res.topology) {
73488
+ print(`
73489
+ ${COLORS.bold}Topology Graph${COLORS.reset}`);
73490
+ print(` Nodes: ${res.topology.nodes.length} Edges: ${res.topology.edges.length}`);
73491
+ }
73492
+ print("");
73493
+ } catch (error50) {
73494
+ handleError(error50);
73495
+ }
73496
+ });
73497
+ cmd.command("spawn <role>").description("Spawn a new agent (queen, worker, specialist, reviewer, monitor)").option("-c, --capabilities <caps>", "Comma-separated capabilities", "general").option("--json", "Output as JSON").action(async (role, opts) => {
73498
+ if (!requireAuth4()) return;
73499
+ const validRoles = ["queen", "worker", "specialist", "reviewer", "monitor"];
73500
+ if (!validRoles.includes(role)) {
73501
+ print(`${COLORS.red}Invalid role:${COLORS.reset} ${role}. Must be one of: ${validRoles.join(", ")}`);
73502
+ return;
73503
+ }
73504
+ try {
73505
+ const capabilities = opts.capabilities.split(",").map((c) => c.trim());
73506
+ const res = await api_client_exports.request("POST", "/swarm/agents", { role, capabilities });
73507
+ if (opts.json) {
73508
+ print(JSON.stringify(res, null, 2));
73509
+ return;
73510
+ }
73511
+ print(`
73512
+ ${COLORS.green}Agent spawned:${COLORS.reset} ${res.id}`);
73513
+ print(` Role: ${res.role}`);
73514
+ print(` Capabilities: ${res.capabilities.join(", ")}`);
73515
+ print(` Status: ${STATUS_COLORS[res.status] || ""}${res.status}${COLORS.reset}
73516
+ `);
73517
+ } catch (error50) {
73518
+ handleError(error50);
73519
+ }
73520
+ });
73521
+ cmd.command("agents").description("List swarm agents").option("--role <role>", "Filter by role").option("--json", "Output as JSON").action(async (opts) => {
73522
+ if (!requireAuth4()) return;
73523
+ try {
73524
+ const query = opts.role ? `?role=${opts.role}` : "";
73525
+ const res = await api_client_exports.request("GET", `/swarm/agents${query}`);
73526
+ if (opts.json) {
73527
+ print(JSON.stringify(res, null, 2));
73528
+ return;
73529
+ }
73530
+ print(`
73531
+ ${COLORS.bold}${COLORS.cyan}Swarm Agents${COLORS.reset} (${res.count})
73532
+ `);
73533
+ print(`${"ID".padEnd(24)} ${"Role".padEnd(12)} ${"Status".padEnd(10)} ${"Done".padEnd(6)} ${"Fail".padEnd(6)} Capabilities`);
73534
+ print(`${"\u2500".repeat(24)} ${"\u2500".repeat(12)} ${"\u2500".repeat(10)} ${"\u2500".repeat(6)} ${"\u2500".repeat(6)} ${"\u2500".repeat(20)}`);
73535
+ for (const a of res.agents) {
73536
+ const color = STATUS_COLORS[a.status] || "";
73537
+ print(
73538
+ `${a.id.padEnd(24)} ${a.role.padEnd(12)} ${color}${a.status.padEnd(10)}${COLORS.reset} ${String(a.completedTasks).padEnd(6)} ${String(a.failedTasks).padEnd(6)} ${a.capabilities.join(", ")}`
73539
+ );
73540
+ }
73541
+ print("");
73542
+ } catch (error50) {
73543
+ handleError(error50);
73544
+ }
73545
+ });
73546
+ cmd.command("submit <type>").description("Submit a task to the swarm").argument("<description>", "Task description").option("-p, --priority <level>", "Priority: critical, high, normal, low", "normal").option("--json", "Output as JSON").action(async (type, description, opts) => {
73547
+ if (!requireAuth4()) return;
73548
+ try {
73549
+ const res = await api_client_exports.request("POST", "/swarm/tasks", {
73550
+ type,
73551
+ description,
73552
+ input: {},
73553
+ priority: opts.priority
73554
+ });
73555
+ if (opts.json) {
73556
+ print(JSON.stringify(res, null, 2));
73557
+ return;
73558
+ }
73559
+ print(`
73560
+ ${COLORS.green}Task submitted:${COLORS.reset} ${res.id}`);
73561
+ print(` Type: ${res.type}`);
73562
+ print(` Priority: ${res.priority}`);
73563
+ print(` Status: ${res.status}`);
73564
+ if (res.assignedAgentId) {
73565
+ print(` Assigned: ${res.assignedAgentId}`);
73566
+ }
73567
+ print("");
73568
+ } catch (error50) {
73569
+ handleError(error50);
73570
+ }
73571
+ });
73572
+ cmd.command("plan <goal>").description("Generate a GOAP execution plan from a goal").option("--parallel", "Enable parallel task groups").option("--json", "Output as JSON").action(async (goal, opts) => {
73573
+ if (!requireAuth4()) return;
73574
+ try {
73575
+ const res = await api_client_exports.request("POST", "/swarm/plan", {
73576
+ goal,
73577
+ currentState: {},
73578
+ goalConditions: [{ key: "deployed", operator: "==", value: true }],
73579
+ parallel: !!opts.parallel
73580
+ });
73581
+ if (opts.json) {
73582
+ print(JSON.stringify(res, null, 2));
73583
+ return;
73584
+ }
73585
+ const feasibleStr = res.feasible ? `${COLORS.green}FEASIBLE${COLORS.reset}` : `${COLORS.red}INFEASIBLE${COLORS.reset}`;
73586
+ print(`
73587
+ ${COLORS.bold}${COLORS.cyan}Goal Planner${COLORS.reset}
73588
+ `);
73589
+ print(` Goal: ${goal}`);
73590
+ print(` Feasible: ${feasibleStr}`);
73591
+ print(` Explanation: ${res.explanation}`);
73592
+ if (res.feasible && res.steps.length > 0) {
73593
+ print(` Total Cost: ${res.totalCost}`);
73594
+ print(` Est. Time: ${Math.round(res.estimatedDurationMs / 1e3)}s`);
73595
+ print(` Par. Groups: ${res.parallelGroups}`);
73596
+ print(`
73597
+ ${COLORS.bold}Execution Steps:${COLORS.reset}
73598
+ `);
73599
+ print(` ${"#".padEnd(4)} ${"Action".padEnd(24)} ${"Agent".padEnd(14)} ${"Group".padEnd(8)} Duration`);
73600
+ print(` ${"\u2500".repeat(4)} ${"\u2500".repeat(24)} ${"\u2500".repeat(14)} ${"\u2500".repeat(8)} ${"\u2500".repeat(10)}`);
73601
+ for (const step of res.steps) {
73602
+ const group = `G${step.parallelGroup}`;
73603
+ const dur = `${Math.round(step.action.estimatedDurationMs / 1e3)}s`;
73604
+ print(
73605
+ ` ${String(step.order + 1).padEnd(4)} ${step.action.name.padEnd(24)} ${step.action.agentCapability.padEnd(14)} ${group.padEnd(8)} ${dur}`
73606
+ );
73607
+ }
73608
+ if (res.steps.some((s) => s.dependencies.length > 0)) {
73609
+ print(`
73610
+ ${COLORS.bold}Dependencies:${COLORS.reset}`);
73611
+ for (const step of res.steps) {
73612
+ if (step.dependencies.length > 0) {
73613
+ print(` ${step.action.name} ${COLORS.dim}<- ${step.dependencies.join(", ")}${COLORS.reset}`);
73614
+ }
73615
+ }
73616
+ }
73617
+ }
73618
+ print("");
73619
+ } catch (error50) {
73620
+ handleError(error50);
73621
+ }
73622
+ });
73623
+ cmd.command("consensus <question>").description("Run a consensus vote across agents").requiredOption("-o, --options <opts>", "Comma-separated vote options").option("--json", "Output as JSON").action(async (question, opts) => {
73624
+ if (!requireAuth4()) return;
73625
+ try {
73626
+ const options = opts.options.split(",").map((o) => o.trim());
73627
+ const res = await api_client_exports.request("POST", "/swarm/consensus", { question, options });
73628
+ if (opts.json) {
73629
+ print(JSON.stringify(res, null, 2));
73630
+ return;
73631
+ }
73632
+ const quorum = res.quorumReached ? `${COLORS.green}QUORUM REACHED${COLORS.reset}` : `${COLORS.yellow}NO QUORUM${COLORS.reset}`;
73633
+ print(`
73634
+ ${COLORS.bold}${COLORS.cyan}Consensus Vote${COLORS.reset}
73635
+ `);
73636
+ print(` Question: ${question}`);
73637
+ print(` Decision: ${COLORS.bold}${res.decision}${COLORS.reset}`);
73638
+ print(` Agreement: ${Math.round(res.agreement * 100)}%`);
73639
+ print(` Status: ${quorum}`);
73640
+ print(` Votes: ${res.votes.length}
73641
+ `);
73642
+ } catch (error50) {
73643
+ handleError(error50);
73644
+ }
73645
+ });
73646
+ cmd.command("memory <action>").description("Vector memory: search, store, stats").argument("[query]", "Search query or content to store").option("--type <type>", "Memory type filter").option("--limit <n>", "Max results", "10").option("--json", "Output as JSON").action(async (action, query, opts) => {
73647
+ if (!requireAuth4()) return;
73648
+ try {
73649
+ if (action === "search" && query) {
73650
+ const res = await api_client_exports.request("POST", "/swarm/memory/search", {
73651
+ query,
73652
+ limit: parseInt(opts.limit, 10),
73653
+ type: opts.type
73654
+ });
73655
+ if (opts.json) {
73656
+ print(JSON.stringify(res, null, 2));
73657
+ return;
73658
+ }
73659
+ print(`
73660
+ ${COLORS.bold}${COLORS.cyan}Memory Search${COLORS.reset} (${res.results.length} results, ${res.searchTimeMs}ms, ${res.method})
73661
+ `);
73662
+ for (const r of res.results) {
73663
+ const truncated = r.entry.content.length > 80 ? r.entry.content.slice(0, 80) + "..." : r.entry.content;
73664
+ print(` ${COLORS.green}#${r.rank}${COLORS.reset} [${r.score.toFixed(3)}] ${COLORS.dim}(${r.entry.type})${COLORS.reset} ${truncated}`);
73665
+ }
73666
+ print("");
73667
+ } else if (action === "stats") {
73668
+ const res = await api_client_exports.request("GET", "/swarm/memory/stats");
73669
+ if (opts.json) {
73670
+ print(JSON.stringify(res, null, 2));
73671
+ return;
73672
+ }
73673
+ print(`
73674
+ ${COLORS.bold}${COLORS.cyan}Vector Memory Stats${COLORS.reset}
73675
+ `);
73676
+ print(` Entries: ${res.totalEntries}`);
73677
+ print(` Dimensions: ${res.dimensions}`);
73678
+ print(` Layers: ${res.layers}`);
73679
+ print(` Avg Import: ${res.avgImportance}`);
73680
+ print(` Memory: ${Math.round(res.memoryBytes / 1024)}KB`);
73681
+ if (res.byType && Object.keys(res.byType).length > 0) {
73682
+ print(`
73683
+ By Type:`);
73684
+ for (const [type, count] of Object.entries(res.byType)) {
73685
+ print(` ${type.padEnd(16)} ${count}`);
73686
+ }
73687
+ }
73688
+ print("");
73689
+ } else {
73690
+ print(`
73691
+ Usage: bootspring swarm memory <search|stats> [query]`);
73692
+ print(` ${COLORS.dim}bootspring swarm memory search "how to fix tests"${COLORS.reset}`);
73693
+ print(` ${COLORS.dim}bootspring swarm memory stats${COLORS.reset}
73694
+ `);
73695
+ }
73696
+ } catch (error50) {
73697
+ handleError(error50);
73698
+ }
73699
+ });
73700
+ cmd.command("topology").description("Show or change swarm topology").option("-s, --set <type>", "Change topology: hierarchical, mesh, ring, star, adaptive").option("--json", "Output as JSON").action(async (opts) => {
73701
+ if (!requireAuth4()) return;
73702
+ try {
73703
+ if (opts.set) {
73704
+ const res = await api_client_exports.request("POST", "/swarm/topology", { topology: opts.set });
73705
+ if (opts.json) {
73706
+ print(JSON.stringify(res, null, 2));
73707
+ return;
73708
+ }
73709
+ print(`
73710
+ ${COLORS.green}Topology changed to:${COLORS.reset} ${opts.set}
73711
+ `);
73712
+ } else {
73713
+ const res = await api_client_exports.request("GET", "/swarm/topology");
73714
+ if (opts.json) {
73715
+ print(JSON.stringify(res, null, 2));
73716
+ return;
73717
+ }
73718
+ print(`
73719
+ ${COLORS.bold}${COLORS.cyan}Topology Graph${COLORS.reset}
73720
+ `);
73721
+ print(` Nodes: ${res.nodes.length} Edges: ${res.edges.length}
73722
+ `);
73723
+ for (const node of res.nodes) {
73724
+ const color = STATUS_COLORS[node.status] || "";
73725
+ print(` ${color}\u25CF${COLORS.reset} ${node.id} (${node.role})`);
73726
+ }
73727
+ if (res.edges.length > 0) {
73728
+ print(`
73729
+ Edges:`);
73730
+ for (const edge of res.edges.slice(0, 20)) {
73731
+ const arrow = edge.type === "parent" ? "\u2192" : "\u2194";
73732
+ print(` ${edge.from} ${arrow} ${edge.to} ${COLORS.dim}(${edge.type})${COLORS.reset}`);
73733
+ }
73734
+ if (res.edges.length > 20) {
73735
+ print(` ${COLORS.dim}... and ${res.edges.length - 20} more edges${COLORS.reset}`);
73736
+ }
73737
+ }
73738
+ print("");
73739
+ }
73740
+ } catch (error50) {
73741
+ handleError(error50);
73742
+ }
73743
+ });
73744
+ cmd.command("visualize").description("Visualize swarm topology as ASCII art").option("--json", "Output as JSON").action(async (opts) => {
73745
+ if (!requireAuth4()) return;
73746
+ try {
73747
+ const res = await api_client_exports.request("GET", "/swarm/snapshot");
73748
+ if (opts.json) {
73749
+ print(JSON.stringify(res, null, 2));
73750
+ return;
73751
+ }
73752
+ const m = res.metrics;
73753
+ const sym = TOPOLOGY_SYMBOLS[m.topology] || "";
73754
+ print(`
73755
+ ${COLORS.bold}${COLORS.cyan}${sym} Swarm Visualization \u2014 ${m.topology}${COLORS.reset}
73756
+ `);
73757
+ const agents = res.agents || [];
73758
+ const queen = agents.find((a) => a.role === "queen");
73759
+ if (m.topology === "hierarchical" || m.topology === "star") {
73760
+ if (queen) {
73761
+ print(` ${COLORS.yellow}\u265B ${queen.id}${COLORS.reset} (queen)`);
73762
+ const children = agents.filter((a) => a.parentId === queen.id);
73763
+ for (let i = 0; i < children.length; i++) {
73764
+ const isLast = i === children.length - 1;
73765
+ const prefix = isLast ? " \u2514\u2500\u2500 " : " \u251C\u2500\u2500 ";
73766
+ const color = STATUS_COLORS[children[i].status] || "";
73767
+ print(`${prefix}${color}\u25CF ${children[i].id}${COLORS.reset} (${children[i].role})`);
73768
+ }
73769
+ }
73770
+ } else if (m.topology === "ring") {
73771
+ for (let i = 0; i < agents.length; i++) {
73772
+ const color = STATUS_COLORS[agents[i].status] || "";
73773
+ const arrow = i < agents.length - 1 ? " \u2192" : ` \u2192 ${agents[0]?.id || ""}`;
73774
+ print(` ${color}\u25CF ${agents[i].id}${COLORS.reset}${arrow}`);
73775
+ }
73776
+ } else {
73777
+ for (const a of agents) {
73778
+ const color = STATUS_COLORS[a.status] || "";
73779
+ print(` ${color}\u25CF${COLORS.reset} ${a.id} (${a.role}) [${a.capabilities.join(", ")}]`);
73780
+ }
73781
+ }
73782
+ print(`
73783
+ ${COLORS.dim}Agents: ${m.totalAgents} | Tasks: ${m.totalTasks} | Completed: ${m.completedTasks} | Phase: ${m.phase}${COLORS.reset}
73784
+ `);
73785
+ } catch (error50) {
73786
+ handleError(error50);
73787
+ }
73788
+ });
73789
+ }
73790
+
73791
+ // src/commands/geo.ts
73792
+ init_cjs_shims();
73793
+ init_src2();
73794
+ function requireAuth5() {
72865
73795
  if (auth_exports.isAuthenticated()) {
72866
73796
  return true;
72867
73797
  }
@@ -72929,7 +73859,7 @@ function printGeoResult(result) {
72929
73859
  function registerGeoCommand(program3) {
72930
73860
  const geo = program3.command("geo").description("GEO-SEO analysis \u2014 optimize for AI search engines");
72931
73861
  geo.command("audit <url>").description("Full GEO + SEO audit with parallel subagents").option("--format <format>", "Output format: markdown | json", "markdown").action(async (url2, opts) => {
72932
- if (!requireAuth4()) return;
73862
+ if (!requireAuth5()) return;
72933
73863
  const spinner = createSpinner("Running GEO audit...").start();
72934
73864
  try {
72935
73865
  const result = await api_client_exports.request("POST", "/geo/audit", { url: url2, options: opts });
@@ -72941,7 +73871,7 @@ function registerGeoCommand(program3) {
72941
73871
  }
72942
73872
  });
72943
73873
  geo.command("quick <url>").description("60-second GEO visibility snapshot").action(async (url2) => {
72944
- if (!requireAuth4()) return;
73874
+ if (!requireAuth5()) return;
72945
73875
  const spinner = createSpinner("Quick GEO scan...").start();
72946
73876
  try {
72947
73877
  const result = await api_client_exports.request("POST", "/geo/quick", { url: url2 });
@@ -72968,7 +73898,7 @@ function registerGeoCommand(program3) {
72968
73898
  ];
72969
73899
  for (const sub of subcommands) {
72970
73900
  geo.command(`${sub.name} ${sub.arg}`).description(sub.desc).action(async (urlOrDomain) => {
72971
- if (!requireAuth4()) return;
73901
+ if (!requireAuth5()) return;
72972
73902
  const spinner = createSpinner(`Running ${sub.name}...`).start();
72973
73903
  try {
72974
73904
  const body = sub.arg === "<domain>" ? { domain: urlOrDomain } : { url: urlOrDomain };
@@ -72982,7 +73912,7 @@ function registerGeoCommand(program3) {
72982
73912
  });
72983
73913
  }
72984
73914
  geo.command("prospect <action>").description("CRM: manage prospects (new, list, show, audit, note, status, pipeline)").argument("[args...]", "Action-specific arguments").action(async (action, args) => {
72985
- if (!requireAuth4()) return;
73915
+ if (!requireAuth5()) return;
72986
73916
  const spinner = createSpinner(`Prospect ${action}...`).start();
72987
73917
  try {
72988
73918
  const result = await api_client_exports.request("POST", "/geo/prospect", { action, data: args });
@@ -72994,7 +73924,7 @@ function registerGeoCommand(program3) {
72994
73924
  }
72995
73925
  });
72996
73926
  geo.command("schemas [name]").description("List JSON-LD schema templates or view a specific one").action(async (name) => {
72997
- if (!requireAuth4()) return;
73927
+ if (!requireAuth5()) return;
72998
73928
  const spinner = createSpinner(name ? `Fetching ${name} schema...` : "Listing schemas...").start();
72999
73929
  try {
73000
73930
  if (name) {
@@ -73030,7 +73960,7 @@ function registerGeoCommand(program3) {
73030
73960
  // src/commands/marketing.ts
73031
73961
  init_cjs_shims();
73032
73962
  init_src2();
73033
- function requireAuth5() {
73963
+ function requireAuth6() {
73034
73964
  if (auth_exports.isAuthenticated()) {
73035
73965
  return true;
73036
73966
  }
@@ -73176,7 +74106,7 @@ function registerMarketingCommand(program3) {
73176
74106
  }
73177
74107
  }
73178
74108
  sub.action(async (...actionArgs) => {
73179
- if (!requireAuth5()) return;
74109
+ if (!requireAuth6()) return;
73180
74110
  const body = {};
73181
74111
  for (let i = 0; i < cmd.args.length; i++) {
73182
74112
  body[cmd.args[i].name] = actionArgs[i];
@@ -73219,7 +74149,7 @@ function registerMarketingCommand(program3) {
73219
74149
  });
73220
74150
  }
73221
74151
  marketing.command("commands").description("List all available marketing commands").action(async () => {
73222
- if (!requireAuth5()) return;
74152
+ if (!requireAuth6()) return;
73223
74153
  const spinner = createSpinner("Fetching marketing commands...").start();
73224
74154
  try {
73225
74155
  const result = await api_client_exports.request("GET", "/marketing/commands");
@@ -73265,7 +74195,7 @@ function registerMarketingCommand(program3) {
73265
74195
  // src/commands/sales.ts
73266
74196
  init_cjs_shims();
73267
74197
  init_src2();
73268
- function requireAuth6() {
74198
+ function requireAuth7() {
73269
74199
  if (auth_exports.isAuthenticated()) {
73270
74200
  return true;
73271
74201
  }
@@ -73386,7 +74316,7 @@ function registerSalesCommand(program3) {
73386
74316
  }
73387
74317
  }
73388
74318
  sub.action(async (...actionArgs) => {
73389
- if (!requireAuth6()) return;
74319
+ if (!requireAuth7()) return;
73390
74320
  const body = {};
73391
74321
  for (let i = 0; i < cmd.args.length; i++) {
73392
74322
  body[cmd.args[i].name] = actionArgs[i];
@@ -73424,7 +74354,7 @@ function registerSalesCommand(program3) {
73424
74354
  });
73425
74355
  }
73426
74356
  sales.command("commands").description("List all available sales commands").action(async () => {
73427
- if (!requireAuth6()) return;
74357
+ if (!requireAuth7()) return;
73428
74358
  const spinner = createSpinner("Fetching sales commands...").start();
73429
74359
  try {
73430
74360
  const result = await api_client_exports.request("GET", "/sales/commands");
@@ -73469,7 +74399,7 @@ function registerSalesCommand(program3) {
73469
74399
  // src/commands/jobs.ts
73470
74400
  init_cjs_shims();
73471
74401
  init_src2();
73472
- function requireAuth7() {
74402
+ function requireAuth8() {
73473
74403
  if (auth_exports.isAuthenticated()) return true;
73474
74404
  print.error('Not logged in. Run "bootspring auth login" first.');
73475
74405
  process.exitCode = 1;
@@ -73478,7 +74408,7 @@ function requireAuth7() {
73478
74408
  function registerJobsCommand(program3) {
73479
74409
  const jobs = program3.command("jobs").description("List and poll async job results");
73480
74410
  jobs.command("list").alias("ls").description("List recent jobs").option("--type <type>", "Filter by type (geo, marketing, sales)").option("--limit <n>", "Number of jobs to show", "20").action(async (opts) => {
73481
- if (!requireAuth7()) return;
74411
+ if (!requireAuth8()) return;
73482
74412
  try {
73483
74413
  const params = new URLSearchParams();
73484
74414
  if (opts.type) params.set("type", opts.type);
@@ -73505,7 +74435,7 @@ ${COLORS.bold}Recent Jobs${COLORS.reset}
73505
74435
  }
73506
74436
  });
73507
74437
  jobs.command("status <jobId>").alias("get").description("Get job status and results").action(async (jobId) => {
73508
- if (!requireAuth7()) return;
74438
+ if (!requireAuth8()) return;
73509
74439
  try {
73510
74440
  const response = await api_client_exports.request("GET", `/jobs/${encodeURIComponent(jobId)}`);
73511
74441
  const job = response.job;
@@ -77931,6 +78861,7 @@ registerSetupCommand(program2);
77931
78861
  registerPipelineCommand(program2);
77932
78862
  registerWorkflowCommand(program2);
77933
78863
  registerHarnessCommand(program2);
78864
+ registerSwarmCommand(program2);
77934
78865
  registerGeoCommand(program2);
77935
78866
  registerMarketingCommand(program2);
77936
78867
  registerSalesCommand(program2);