swarmkit 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  export interface WizardOptions {
2
2
  noPrefix?: boolean;
3
+ forceGlobal?: boolean;
3
4
  }
4
5
  export declare function runWizard(opts?: WizardOptions): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import chalk from "chalk";
2
- import { select } from "@inquirer/prompts";
3
- import { isFirstRun, readConfig, writeConfig, ensureConfigDir } from "../../config/global.js";
2
+ import { select, confirm } from "@inquirer/prompts";
3
+ import { isFirstRun, readConfig, writeConfig, ensureConfigDir, isConfigOutdated, getSwarmkitVersion } from "../../config/global.js";
4
4
  import * as ui from "../../utils/ui.js";
5
5
  import { getActiveIntegrations } from "../../packages/registry.js";
6
6
  import { isClaudeCliAvailable } from "../../packages/installer.js";
@@ -15,11 +15,28 @@ export async function runWizard(opts) {
15
15
  console.log();
16
16
  console.log(` ${chalk.bold("swarmkit")} ${chalk.dim("— multi-agent infrastructure toolkit")}`);
17
17
  console.log();
18
- if (isFirstRun()) {
18
+ if (isFirstRun() || opts?.forceGlobal) {
19
19
  await runFirstTimeSetup(opts);
20
20
  }
21
21
  else {
22
- await runProjectSetup(opts);
22
+ const config = readConfig();
23
+ if (isConfigOutdated(config)) {
24
+ ui.warn(`Global config was created with swarmkit ${config.configVersion ?? "< 0.1.0"}, ` +
25
+ `but you are now running ${getSwarmkitVersion()}.`);
26
+ const shouldRerun = await confirm({
27
+ message: "Re-run global setup to update your configuration?",
28
+ default: true,
29
+ });
30
+ if (shouldRerun) {
31
+ await runFirstTimeSetup(opts);
32
+ }
33
+ else {
34
+ await runProjectSetup(opts);
35
+ }
36
+ }
37
+ else {
38
+ await runProjectSetup(opts);
39
+ }
23
40
  }
24
41
  }
25
42
  async function runFirstTimeSetup(opts) {
@@ -39,9 +56,10 @@ async function runFirstTimeSetup(opts) {
39
56
  await initGlobal(state);
40
57
  // Step 5: Project init (if in a project directory)
41
58
  await initProject(state);
42
- // Persist prefix preference
59
+ // Persist prefix preference and config version
43
60
  const config = readConfig();
44
61
  config.usePrefix = state.usePrefix;
62
+ config.configVersion = getSwarmkitVersion();
45
63
  writeConfig(config);
46
64
  // Summary
47
65
  printSummary(state);
@@ -3,9 +3,13 @@ export function registerInitCommand(program) {
3
3
  .command("init")
4
4
  .description("Interactive setup wizard")
5
5
  .option("--no-prefix", "Use flat layout (e.g. .opentasks/) instead of nesting under .swarm/")
6
+ .option("-g, --global", "Re-run full global setup (even if already configured)")
6
7
  .action(async (opts) => {
7
8
  // Dynamic import to avoid loading @inquirer/prompts for other commands
8
9
  const { runWizard } = await import("./init/wizard.js");
9
- await runWizard({ noPrefix: opts.prefix === false });
10
+ await runWizard({
11
+ noPrefix: opts.prefix === false,
12
+ forceGlobal: opts.global === true,
13
+ });
10
14
  });
11
15
  }
@@ -7,6 +7,8 @@ export interface GlobalConfig {
7
7
  embeddingModel?: string;
8
8
  /** Whether project configs are nested under .swarm/ (default true) */
9
9
  usePrefix?: boolean;
10
+ /** The swarmkit version that last ran full global setup */
11
+ configVersion?: string;
10
12
  }
11
13
  /** Get the swarmkit config directory path (~/.swarmkit/) */
12
14
  export declare function getConfigDir(): string;
@@ -24,3 +26,11 @@ export declare function writeConfig(config: GlobalConfig): void;
24
26
  export declare function addInstalledPackages(packages: string[]): void;
25
27
  /** Remove a package from the installed list */
26
28
  export declare function removeInstalledPackage(packageName: string): void;
29
+ /** Get the current swarmkit version from package.json */
30
+ export declare function getSwarmkitVersion(): string;
31
+ /**
32
+ * Check if the config version is outdated compared to the current swarmkit version.
33
+ * Outdated if configVersion is missing or major/minor version differs.
34
+ * Patch-only bumps are not considered outdated.
35
+ */
36
+ export declare function isConfigOutdated(config: GlobalConfig, currentVersion?: string): boolean;
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
- import { join } from "node:path";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
4
5
  const DEFAULT_CONFIG = {
5
6
  installedPackages: [],
6
7
  };
@@ -69,3 +70,35 @@ export function removeInstalledPackage(packageName) {
69
70
  config.installedPackages = config.installedPackages.filter((p) => p !== packageName);
70
71
  writeConfig(config);
71
72
  }
73
+ /** Get the current swarmkit version from package.json */
74
+ export function getSwarmkitVersion() {
75
+ try {
76
+ const __dirname = dirname(fileURLToPath(import.meta.url));
77
+ const pkgPath = join(__dirname, "..", "package.json");
78
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
79
+ return pkg.version;
80
+ }
81
+ catch {
82
+ return "0.0.0";
83
+ }
84
+ }
85
+ function parseVersion(version) {
86
+ const parts = version.split(".").map(Number);
87
+ return {
88
+ major: parts[0] ?? 0,
89
+ minor: parts[1] ?? 0,
90
+ patch: parts[2] ?? 0,
91
+ };
92
+ }
93
+ /**
94
+ * Check if the config version is outdated compared to the current swarmkit version.
95
+ * Outdated if configVersion is missing or major/minor version differs.
96
+ * Patch-only bumps are not considered outdated.
97
+ */
98
+ export function isConfigOutdated(config, currentVersion) {
99
+ if (!config.configVersion)
100
+ return true;
101
+ const current = parseVersion(currentVersion ?? getSwarmkitVersion());
102
+ const saved = parseVersion(config.configVersion);
103
+ return current.major !== saved.major || current.minor !== saved.minor;
104
+ }
@@ -12,7 +12,7 @@ vi.mock("node:os", async () => {
12
12
  };
13
13
  });
14
14
  // Import after mock is set up
15
- const { getConfigDir, getConfigPath, ensureConfigDir, isFirstRun, readConfig, writeConfig, addInstalledPackages, removeInstalledPackage, } = await import("./global.js");
15
+ const { getConfigDir, getConfigPath, ensureConfigDir, isFirstRun, readConfig, writeConfig, addInstalledPackages, removeInstalledPackage, getSwarmkitVersion, isConfigOutdated, } = await import("./global.js");
16
16
  describe("config/global", () => {
17
17
  beforeEach(() => {
18
18
  tempHome = mkdtempSync(join(tmpdir(), "swarmkit-test-"));
@@ -164,4 +164,37 @@ describe("config/global", () => {
164
164
  expect(config.embeddingProvider).toBe("gemini");
165
165
  });
166
166
  });
167
+ describe("getSwarmkitVersion", () => {
168
+ it("returns a semver string", () => {
169
+ const version = getSwarmkitVersion();
170
+ expect(version).toMatch(/^\d+\.\d+\.\d+/);
171
+ });
172
+ });
173
+ describe("isConfigOutdated", () => {
174
+ it("returns true when configVersion is missing", () => {
175
+ const config = { installedPackages: [] };
176
+ expect(isConfigOutdated(config, "1.0.0")).toBe(true);
177
+ });
178
+ it("returns false when versions match exactly", () => {
179
+ const config = { installedPackages: [], configVersion: "1.2.3" };
180
+ expect(isConfigOutdated(config, "1.2.3")).toBe(false);
181
+ });
182
+ it("returns false for patch-only difference", () => {
183
+ const config = { installedPackages: [], configVersion: "1.2.0" };
184
+ expect(isConfigOutdated(config, "1.2.5")).toBe(false);
185
+ });
186
+ it("returns true when minor version differs", () => {
187
+ const config = { installedPackages: [], configVersion: "1.0.0" };
188
+ expect(isConfigOutdated(config, "1.1.0")).toBe(true);
189
+ });
190
+ it("returns true when major version differs", () => {
191
+ const config = { installedPackages: [], configVersion: "0.1.0" };
192
+ expect(isConfigOutdated(config, "1.0.0")).toBe(true);
193
+ });
194
+ it("uses getSwarmkitVersion when currentVersion is not provided", () => {
195
+ const version = getSwarmkitVersion();
196
+ const config = { installedPackages: [], configVersion: version };
197
+ expect(isConfigOutdated(config)).toBe(false);
198
+ });
199
+ });
167
200
  });
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export type { InstallResult, UpdateResult } from "./packages/installer.js";
5
5
  export { isInstalledPlugin, registerPlugin, } from "./packages/plugin.js";
6
6
  export { PROJECT_CONFIG_DIRS, PROJECT_INIT_ORDER, GLOBAL_CONFIG_DIRS, isProjectInit, isGlobalInit, initProjectPackage, initGlobalPackage, } from "./packages/setup.js";
7
7
  export type { InitContext, GlobalContext, OpenhiveOptions, SetupResult, } from "./packages/setup.js";
8
- export { readConfig, writeConfig, isFirstRun, getConfigDir, addInstalledPackages, removeInstalledPackage, } from "./config/global.js";
8
+ export { readConfig, writeConfig, isFirstRun, getConfigDir, addInstalledPackages, removeInstalledPackage, getSwarmkitVersion, isConfigOutdated, } from "./config/global.js";
9
9
  export type { GlobalConfig } from "./config/global.js";
10
10
  export { readKey, writeKey, deleteKey, listKeys, hasKey, } from "./config/keys.js";
11
11
  export { runAllChecks } from "./doctor/checks.js";
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ export { PACKAGES, BUNDLES, INTEGRATIONS, getBundlePackages, getActiveIntegratio
3
3
  export { installPackages, uninstallPackage, getInstalledVersion, getLatestVersion, updatePackages, isClaudeCliAvailable, getGlobalPackagePath, } from "./packages/installer.js";
4
4
  export { isInstalledPlugin, registerPlugin, } from "./packages/plugin.js";
5
5
  export { PROJECT_CONFIG_DIRS, PROJECT_INIT_ORDER, GLOBAL_CONFIG_DIRS, isProjectInit, isGlobalInit, initProjectPackage, initGlobalPackage, } from "./packages/setup.js";
6
- export { readConfig, writeConfig, isFirstRun, getConfigDir, addInstalledPackages, removeInstalledPackage, } from "./config/global.js";
6
+ export { readConfig, writeConfig, isFirstRun, getConfigDir, addInstalledPackages, removeInstalledPackage, getSwarmkitVersion, isConfigOutdated, } from "./config/global.js";
7
7
  export { readKey, writeKey, deleteKey, listKeys, hasKey, } from "./config/keys.js";
8
8
  export { runAllChecks } from "./doctor/checks.js";
9
9
  export { readCredentials, writeCredentials, deleteCredentials, isLoggedIn, } from "./hub/credentials.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swarmkit",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Multi-agent infa toolkit",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",