@uniqbit/mate-core 0.15.0-canary.3 → 0.15.0-canary.7
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
package/src/cli/main.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getActiveDistribution } from "../distribution";
|
|
2
2
|
import {
|
|
3
|
+
enforceUpdateIfRequired,
|
|
3
4
|
scheduleBackgroundCheck,
|
|
4
5
|
showUpdateBannerIfAvailable,
|
|
5
6
|
UpdateStateStore,
|
|
@@ -56,8 +57,15 @@ export async function main(argv = process.argv, deps: MainDeps = mainDeps): Prom
|
|
|
56
57
|
command === "cap" && findPluginCliCommand(subcommand, rest[0]) !== undefined;
|
|
57
58
|
if (!isPluginCommand) {
|
|
58
59
|
const updateStore = new UpdateStateStore();
|
|
59
|
-
await showUpdateBannerIfAvailable(updateStore);
|
|
60
60
|
scheduleBackgroundCheck(updateStore);
|
|
61
|
+
if (
|
|
62
|
+
!isInstallRecoveryCommand(command, subcommand) &&
|
|
63
|
+
(await enforceUpdateIfRequired(updateStore))
|
|
64
|
+
) {
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await showUpdateBannerIfAvailable(updateStore);
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
if (!command || command === "help" || command === "--help" || command === "-h") {
|
package/src/distribution.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { PluginRegistry } from "./tools/setup/registry";
|
|
2
2
|
|
|
3
3
|
export interface DistributionUpdateConfig {
|
|
4
|
-
/** npm package whose versions are checked and installed by `mate update`. */
|
|
5
|
-
packageName
|
|
6
|
-
/** npm registry used for update checks and downloads. */
|
|
7
|
-
registry
|
|
4
|
+
/** npm package whose versions are checked and installed by `mate update`. Defaults to `@uniqbit/<name>`. */
|
|
5
|
+
packageName?: string;
|
|
6
|
+
/** npm registry used for update checks and downloads. Defaults to public npm. */
|
|
7
|
+
registry?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Refuse to run commands while a newer version is available, instead of
|
|
10
|
+
* only printing a banner. Install-recovery commands (`install`, `update`,
|
|
11
|
+
* `doctor`, `help`, `companion setup|link`) stay available so the user can
|
|
12
|
+
* actually upgrade.
|
|
13
|
+
*/
|
|
14
|
+
enforce?: boolean;
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
/** Identity and version of the distribution assembled through `createMate`. */
|
|
@@ -13,7 +13,7 @@ interface UpdateState {
|
|
|
13
13
|
latestVersion: string | null;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const
|
|
16
|
+
const SIX_HOURS_MS = 6 * 60 * 60 * 1000;
|
|
17
17
|
|
|
18
18
|
export const updateCheckerDeps = {
|
|
19
19
|
now: () => Date.now(),
|
|
@@ -34,11 +34,12 @@ export function getCurrentVersion(): string {
|
|
|
34
34
|
return getActiveDistribution().config.version;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export function getUpdateConfig(): DistributionUpdateConfig {
|
|
37
|
+
export function getUpdateConfig(): Required<DistributionUpdateConfig> {
|
|
38
38
|
const { name, update } = getActiveDistribution().config;
|
|
39
39
|
return {
|
|
40
40
|
packageName: update?.packageName ?? `@uniqbit/${name}`,
|
|
41
41
|
registry: update?.registry ?? PUBLIC_NPM_REGISTRY,
|
|
42
|
+
enforce: update?.enforce ?? false,
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -69,6 +70,28 @@ export async function showUpdateBannerIfAvailable(store: UpdateStateStore): Prom
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Distributions that set `update.enforce` refuse to run further commands while
|
|
75
|
+
* a cached newer version is available. Returns true when the current command
|
|
76
|
+
* must stop; state-load failures never block.
|
|
77
|
+
*/
|
|
78
|
+
export async function enforceUpdateIfRequired(store: UpdateStateStore): Promise<boolean> {
|
|
79
|
+
if (!getUpdateConfig().enforce) return false;
|
|
80
|
+
try {
|
|
81
|
+
const state = await store.load();
|
|
82
|
+
if (!state.latestVersion) return false;
|
|
83
|
+
const current = getCurrentVersion();
|
|
84
|
+
if (!isNewer(state.latestVersion, current)) return false;
|
|
85
|
+
process.stderr.write(
|
|
86
|
+
`\n${frameworkConfig.name}: update required (${current} → ${state.latestVersion})\n`,
|
|
87
|
+
);
|
|
88
|
+
process.stderr.write(` Run \`${frameworkConfig.name} update\` before continuing.\n\n`);
|
|
89
|
+
return true;
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
72
95
|
export async function fetchLatestVersion(): Promise<string> {
|
|
73
96
|
const { packageName, registry } = getUpdateConfig();
|
|
74
97
|
return fetchPublicPackageVersion(packageName, registry);
|
|
@@ -79,7 +102,7 @@ export function scheduleBackgroundCheck(store: UpdateStateStore): void {
|
|
|
79
102
|
try {
|
|
80
103
|
const state = await store.load();
|
|
81
104
|
const lastChecked = state.lastChecked ? new Date(state.lastChecked).getTime() : 0;
|
|
82
|
-
if (updateCheckerDeps.now() - lastChecked <
|
|
105
|
+
if (updateCheckerDeps.now() - lastChecked < SIX_HOURS_MS) return;
|
|
83
106
|
const latestVersion = await fetchLatestVersion();
|
|
84
107
|
await store.save({ lastChecked: updateCheckerDeps.toIsoString(), latestVersion });
|
|
85
108
|
} catch {
|
|
@@ -34,6 +34,7 @@ async function configureClaudeGuidance(companionPath: string): Promise<void> {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const BASE_WORKING_REPO_LOCAL_EXCLUDE_ENTRIES = [".claude/settings.local.json"];
|
|
37
|
+
const COMPANION_GITIGNORE_ENTRIES = [...BASE_WORKING_REPO_LOCAL_EXCLUDE_ENTRIES, ".claude/state/"];
|
|
37
38
|
// Union of all managed exclude entries — used to identify which lines we own.
|
|
38
39
|
const ALL_MANAGED_EXCLUDE_ENTRIES = new Set([
|
|
39
40
|
...BASE_WORKING_REPO_LOCAL_EXCLUDE_ENTRIES,
|
|
@@ -670,7 +671,7 @@ export function createClaudePlugin(): ProviderPlugin {
|
|
|
670
671
|
description: "Install Claude companion files, hooks, and guidance.",
|
|
671
672
|
defaultSelected: true,
|
|
672
673
|
isEnabled: (config) => (config.profiles.default?.allowedAgents ?? []).includes("claude"),
|
|
673
|
-
gitignoreEntries: () =>
|
|
674
|
+
gitignoreEntries: () => COMPANION_GITIGNORE_ENTRIES,
|
|
674
675
|
hosting: {
|
|
675
676
|
mcp: {
|
|
676
677
|
async register(ctx: SetupContext, descriptor: McpServerDescriptor) {
|