@girardmedia/bootspring 2.3.4 → 2.3.6

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/README.md CHANGED
@@ -12,7 +12,8 @@ Bootspring is an AI-powered development platform that provides intelligent conte
12
12
  - **Preseed → Seed → Scaffold Pipeline** - Go from idea to working code with AI-assisted document generation
13
13
  - **Universal Drop Zone** - Drop any files and let AI analyze and categorize them for you
14
14
  - **Intelligent Context Management** - Automatically generates and maintains AI context for your project
15
- - **Specialized Agents** - 12+ expert agents for database, security, frontend, backend, and more
15
+ - **Parallel Workflow Orchestration** - Multi-phase parallel execution plans with 36 specialized agents
16
+ - **Specialized Agents** - 36 expert agents for database, security, frontend, backend, and more
16
17
  - **MCP Integration** - Native Model Context Protocol server for seamless AI assistant integration
17
18
  - **Entitlement-Ready Skill Catalog** - Built-in patterns public, curated external catalog policy-gated
18
19
  - **Plugin System** - Extensible architecture for auth, payments, database, testing, security
@@ -3347,6 +3347,7 @@ __export(dist_exports, {
3347
3347
  saveProjectScopedSession: () => saveProjectScopedSession,
3348
3348
  saveSession: () => saveSession,
3349
3349
  session: () => session_exports,
3350
+ setAuthFailureHandler: () => setAuthFailureHandler,
3350
3351
  setCurrentProject: () => setCurrentProject,
3351
3352
  slugify: () => slugify,
3352
3353
  startDeviceFlow: () => startDeviceFlow,
@@ -3389,6 +3390,7 @@ function decrypt(encrypted) {
3389
3390
  return JSON.parse(decrypted);
3390
3391
  }
3391
3392
  function getCredentials() {
3393
+ if (_credentialCache) return _credentialCache.value;
3392
3394
  try {
3393
3395
  if (import_fs2.default.existsSync(CREDENTIALS_FILE)) {
3394
3396
  const raw = JSON.parse(import_fs2.default.readFileSync(CREDENTIALS_FILE, "utf-8"));
@@ -3396,11 +3398,17 @@ function getCredentials() {
3396
3398
  if (raw && typeof raw === "object" && !raw.iv && !raw.data) {
3397
3399
  saveCredentials(decrypted);
3398
3400
  }
3401
+ _credentialCache = { resolved: true, value: decrypted };
3399
3402
  return decrypted;
3400
3403
  }
3401
- } catch (err) {
3402
- console.error("[bootspring] Failed to read credentials:", err.message);
3404
+ } catch {
3405
+ _credentialDecryptFailed = true;
3406
+ try {
3407
+ import_fs2.default.unlinkSync(CREDENTIALS_FILE);
3408
+ } catch {
3409
+ }
3403
3410
  }
3411
+ _credentialCache = { resolved: true, value: null };
3404
3412
  return null;
3405
3413
  }
3406
3414
  function saveCredentials(credentials) {
@@ -3411,6 +3419,7 @@ function saveCredentials(credentials) {
3411
3419
  JSON.stringify(encrypted, null, 2),
3412
3420
  { mode: 384 }
3413
3421
  );
3422
+ _credentialCache = null;
3414
3423
  }
3415
3424
  function clearCredentials() {
3416
3425
  try {
@@ -3419,6 +3428,8 @@ function clearCredentials() {
3419
3428
  }
3420
3429
  } catch {
3421
3430
  }
3431
+ _credentialCache = null;
3432
+ _credentialDecryptFailed = false;
3422
3433
  }
3423
3434
  function getToken() {
3424
3435
  const creds = getCredentials();
@@ -3518,9 +3529,13 @@ function getApiKey() {
3518
3529
  if (storedApiKey) return storedApiKey;
3519
3530
  const legacyApiKey = getLegacyProjectApiKey();
3520
3531
  if (legacyApiKey) {
3521
- if (!legacyProjectApiKeyWarned) {
3522
- legacyProjectApiKeyWarned = true;
3523
- console.warn("[bootspring] Using legacy .bootspring.json apiKey fallback.");
3532
+ if (_credentialDecryptFailed) {
3533
+ try {
3534
+ saveCredentials({ apiKey: legacyApiKey });
3535
+ _credentialCache = null;
3536
+ _credentialDecryptFailed = false;
3537
+ } catch {
3538
+ }
3524
3539
  }
3525
3540
  return legacyApiKey;
3526
3541
  }
@@ -3731,6 +3746,9 @@ function clearDeviceInfo() {
3731
3746
  } catch {
3732
3747
  }
3733
3748
  }
3749
+ function setAuthFailureHandler(handler) {
3750
+ _onAuthFailure = handler;
3751
+ }
3734
3752
  function formatHttpErrorBody(body, statusCode) {
3735
3753
  const raw = String(body || "").trim();
3736
3754
  if (!raw) return `API Error (${statusCode || "unknown"})`;
@@ -3762,7 +3780,7 @@ function appendQueryParams(url, data) {
3762
3780
  }
3763
3781
  return url;
3764
3782
  }
3765
- async function request(method, path310, data = null, options = {}) {
3783
+ async function rawRequest(method, path310, data, options) {
3766
3784
  const authHeaders = await resolveAuthHeaders();
3767
3785
  const url = appendQueryParams(new URL(`/api/${API_VERSION}${path310}`, API_BASE), method === "GET" ? data : null);
3768
3786
  const isHttps = url.protocol === "https:";
@@ -3824,6 +3842,19 @@ async function request(method, path310, data = null, options = {}) {
3824
3842
  req.end();
3825
3843
  });
3826
3844
  }
3845
+ async function request(method, path310, data = null, options = {}) {
3846
+ try {
3847
+ return await rawRequest(method, path310, data, options);
3848
+ } catch (err) {
3849
+ if (err.status === 401 && _onAuthFailure && !options._authRetried) {
3850
+ const reauthOk = await _onAuthFailure();
3851
+ if (reauthOk) {
3852
+ return rawRequest(method, path310, data, { ...options, _authRetried: true, noCache: true });
3853
+ }
3854
+ }
3855
+ throw err;
3856
+ }
3857
+ }
3827
3858
  async function healthCheck() {
3828
3859
  try {
3829
3860
  const url = new URL("/health", API_BASE);
@@ -4100,7 +4131,7 @@ function validateSlug(slug) {
4100
4131
  }
4101
4132
  return { valid: true, sanitized: slug };
4102
4133
  }
4103
- var import_fs2, import_path2, import_os, import_crypto, import_https, import_http, import_fs3, import_path3, __defProp2, __export2, auth_exports, BOOTSPRING_DIR, CREDENTIALS_FILE, CONFIG_FILE, DEVICE_FILE, getEncryptionKey, legacyProjectApiKeyWarned, api_client_exports, API_BASE, API_VERSION, cache, CACHE_TTL, session_exports, SESSION_FILE, LOCAL_CONFIG_NAME, PROJECT_SCOPE_MARKERS, LIMITS, PATTERNS, SHELL_DANGEROUS_CHARS;
4134
+ var import_fs2, import_path2, import_os, import_crypto, import_https, import_http, import_fs3, import_path3, __defProp2, __export2, auth_exports, BOOTSPRING_DIR, CREDENTIALS_FILE, CONFIG_FILE, DEVICE_FILE, _credentialCache, _credentialDecryptFailed, getEncryptionKey, api_client_exports, API_BASE, API_VERSION, _onAuthFailure, cache, CACHE_TTL, session_exports, SESSION_FILE, LOCAL_CONFIG_NAME, PROJECT_SCOPE_MARKERS, LIMITS, PATTERNS, SHELL_DANGEROUS_CHARS;
4104
4135
  var init_dist2 = __esm({
4105
4136
  "../../packages/core/dist/index.mjs"() {
4106
4137
  "use strict";
@@ -4168,11 +4199,12 @@ var init_dist2 = __esm({
4168
4199
  CREDENTIALS_FILE = import_path2.default.join(BOOTSPRING_DIR, "credentials.json");
4169
4200
  CONFIG_FILE = import_path2.default.join(BOOTSPRING_DIR, "config.json");
4170
4201
  DEVICE_FILE = import_path2.default.join(BOOTSPRING_DIR, "device.json");
4202
+ _credentialCache = null;
4203
+ _credentialDecryptFailed = false;
4171
4204
  getEncryptionKey = () => {
4172
4205
  const machineId = import_os.default.hostname() + import_os.default.userInfo().username;
4173
4206
  return import_crypto.default.createHash("sha256").update(machineId).digest();
4174
4207
  };
4175
- legacyProjectApiKeyWarned = false;
4176
4208
  api_client_exports = {};
4177
4209
  __export2(api_client_exports, {
4178
4210
  API_BASE: () => API_BASE,
@@ -4181,10 +4213,12 @@ var init_dist2 = __esm({
4181
4213
  healthCheck: () => healthCheck,
4182
4214
  pollDeviceToken: () => pollDeviceToken,
4183
4215
  request: () => request,
4216
+ setAuthFailureHandler: () => setAuthFailureHandler,
4184
4217
  startDeviceFlow: () => startDeviceFlow
4185
4218
  });
4186
4219
  API_BASE = process.env["BOOTSPRING_API_URL"] || "https://api.bootspring.com";
4187
4220
  API_VERSION = "v1";
4221
+ _onAuthFailure = null;
4188
4222
  cache = /* @__PURE__ */ new Map();
4189
4223
  CACHE_TTL = 6e4;
4190
4224
  session_exports = {};
@@ -4254,6 +4288,9 @@ var {
4254
4288
  Help
4255
4289
  } = import_index.default;
4256
4290
 
4291
+ // src/index.ts
4292
+ init_dist2();
4293
+
4257
4294
  // src/commands/auth.ts
4258
4295
  init_cjs_shims();
4259
4296
  var import_child_process = require("child_process");
@@ -19449,4 +19486,22 @@ registerWatchCommand(program2);
19449
19486
  registerContextCommand(program2);
19450
19487
  registerManagerCommand(program2);
19451
19488
  registerSetupCommand(program2);
19489
+ api_client_exports.setAuthFailureHandler(async () => {
19490
+ const legacyKey = auth_exports.getLegacyProjectApiKey();
19491
+ if (legacyKey) {
19492
+ try {
19493
+ const response = await api_client_exports.request("POST", "/keys/validate", { apiKey: legacyKey }, { _authRetried: true });
19494
+ if (response.valid) {
19495
+ auth_exports.loginWithApiKey(legacyKey, response);
19496
+ return true;
19497
+ }
19498
+ } catch {
19499
+ }
19500
+ }
19501
+ console.error(`
19502
+ ${COLORS.yellow}\u26A0${COLORS.reset} Session expired or invalid.`);
19503
+ console.error(` Run ${COLORS.bold}bootspring auth login${COLORS.reset} to re-authenticate.
19504
+ `);
19505
+ return false;
19506
+ });
19452
19507
  program2.parse();
package/dist/core.js CHANGED
@@ -1600,7 +1600,7 @@ var require_package = __commonJS({
1600
1600
  "package.json"(exports2, module2) {
1601
1601
  module2.exports = {
1602
1602
  name: "@girardmedia/bootspring",
1603
- version: "2.3.4",
1603
+ version: "2.3.6",
1604
1604
  description: "Thin client for Bootspring cloud MCP, hosted agents, and paywalled workflow intelligence",
1605
1605
  keywords: [
1606
1606
  "ai",
@@ -45,7 +45,7 @@ var require_package = __commonJS({
45
45
  "package.json"(exports2, module2) {
46
46
  module2.exports = {
47
47
  name: "@girardmedia/bootspring",
48
- version: "2.3.4",
48
+ version: "2.3.6",
49
49
  description: "Thin client for Bootspring cloud MCP, hosted agents, and paywalled workflow intelligence",
50
50
  keywords: [
51
51
  "ai",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@girardmedia/bootspring",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "Thin client for Bootspring cloud MCP, hosted agents, and paywalled workflow intelligence",
5
5
  "keywords": [
6
6
  "ai",