karajan-code 3.12.0 → 3.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "karajan-code",
3
- "version": "3.12.0",
3
+ "version": "3.12.1",
4
4
  "description": "Local multi-agent coding orchestrator with TDD, SonarQube, and code review pipeline",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0",
@@ -304,26 +304,11 @@ export function registerMeta(program, { pkgVersion }) {
304
304
  .command("update")
305
305
  .description("Update karajan-code to the latest version from npm")
306
306
  .action(async () => {
307
- // Audit follow-up: was execaCommand (shell parsing). Inputs are
308
- // constants today, but the project standard since #555 is execa
309
- // with arg arrays (no shell). Migrated for consistency.
310
- const { execa } = await import("execa");
311
- console.log(`Current version: ${pkgVersion}`);
312
- console.log("Checking for updates...");
313
- try {
314
- const { stdout } = await execa("npm", ["view", "karajan-code", "version"]);
315
- const latest = stdout.trim();
316
- if (latest === pkgVersion) {
317
- console.log(`Already on the latest version (${pkgVersion}).`);
318
- return;
319
- }
320
- console.log(`Updating ${pkgVersion} → ${latest}...`);
321
- await execa("npm", ["install", "-g", "karajan-code@latest"], { stdio: "inherit" });
322
- console.log(`Updated to ${latest}. Restart Claude to pick up the new MCP server.`);
323
- } catch (err) {
324
- console.error(`Update failed: ${err.message}`);
325
- process.exit(1);
326
- }
307
+ // Output-capturing self-update: npm's deprecation/allow-scripts/funding
308
+ // warnings are hidden on success and only surfaced when the install fails.
309
+ const { performSelfUpdate } = await import("../utils/update-check.js");
310
+ const result = await performSelfUpdate({ currentVersion: pkgVersion });
311
+ if (!result.ok) process.exit(1);
327
312
  });
328
313
 
329
314
  program
@@ -103,6 +103,53 @@ export async function printUpdateNotice(currentVersion) {
103
103
  }
104
104
  }
105
105
 
106
+ /**
107
+ * Run the npm-channel self-update (`kj update`). Captures npm's output instead
108
+ * of streaming it: a successful update shows only the progress + result line,
109
+ * so npm's deprecation / allow-scripts / funding noise — build plumbing, not
110
+ * actionable for whoever runs the command — never reaches the user. On failure
111
+ * the captured stdout/stderr IS surfaced, so real errors (native build,
112
+ * permissions) stay diagnosable — never a silent failure.
113
+ *
114
+ * @param {Object} opts
115
+ * @param {string} opts.currentVersion - version of the running kj
116
+ * @param {(cmd: string, args: string[]) => Promise<{stdout: string, stderr: string}>} [opts.exec] - injectable runner (defaults to execa)
117
+ * @param {Console} [opts.logger]
118
+ * @returns {Promise<{ ok: boolean, alreadyLatest?: boolean, latest?: string }>}
119
+ */
120
+ export async function performSelfUpdate({ currentVersion, exec, logger = console } = {}) {
121
+ const run = exec || (async (cmd, args) => (await import("execa")).execa(cmd, args));
122
+ logger.log(`Current version: ${currentVersion}`);
123
+ logger.log("Checking for updates...");
124
+
125
+ let latest;
126
+ try {
127
+ const { stdout } = await run("npm", ["view", PACKAGE_NAME, "version"]);
128
+ latest = stdout.trim();
129
+ } catch (err) {
130
+ logger.error(`Update failed: ${err.shortMessage || err.message}`);
131
+ return { ok: false };
132
+ }
133
+
134
+ if (latest === currentVersion) {
135
+ logger.log(`Already on the latest version (${currentVersion}).`);
136
+ return { ok: true, alreadyLatest: true, latest };
137
+ }
138
+
139
+ logger.log(`Updating ${currentVersion} → ${latest}... (this can take a few minutes)`);
140
+ try {
141
+ // No stdio:inherit — capture and drop npm's warnings on the success path.
142
+ await run("npm", ["install", "-g", `${PACKAGE_NAME}@latest`]);
143
+ logger.log(`Updated to ${latest}. Restart Claude to pick up the new MCP server.`);
144
+ return { ok: true, latest };
145
+ } catch (err) {
146
+ if (err.stdout) logger.error(err.stdout);
147
+ if (err.stderr) logger.error(err.stderr);
148
+ logger.error(`Update failed: ${err.shortMessage || err.message}`);
149
+ return { ok: false };
150
+ }
151
+ }
152
+
106
153
  /** Simple semver compare: returns >0 if a > b, <0 if a < b, 0 if equal */
107
154
  function compareVersions(a, b) {
108
155
  const pa = a.split(".").map(Number);