forkit-connect 0.1.28 → 0.1.30
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.js +90 -26
- package/dist/v1/update.d.ts +5 -1
- package/dist/v1/update.js +53 -9
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -78,6 +78,7 @@ const CLI_FALLBACK_PLAN_LIMITS = {
|
|
|
78
78
|
};
|
|
79
79
|
const PUBLIC_COMMANDS = [
|
|
80
80
|
['init', 'Initialize local Connect identity and privacy posture'],
|
|
81
|
+
['version', 'Print the Forkit Connect CLI version'],
|
|
81
82
|
['login', 'Link this device to your Forkit.dev account'],
|
|
82
83
|
['logout', 'Remove the stored Forkit.dev session from this device'],
|
|
83
84
|
['status', 'Show account, scope, daemon, and queue status'],
|
|
@@ -93,6 +94,19 @@ const PUBLIC_COMMANDS = [
|
|
|
93
94
|
['ignore', 'Deny one detected local model on this device'],
|
|
94
95
|
['doctor', 'Run local environment diagnostics'],
|
|
95
96
|
];
|
|
97
|
+
const START_HERE_COMMANDS = [
|
|
98
|
+
['forkit-connect login', 'Pair this machine with your Forkit.dev account'],
|
|
99
|
+
['forkit-connect workspace status', 'Confirm the active workspace and project scope'],
|
|
100
|
+
['forkit-connect scan', 'Find local models, agents, and runtimes'],
|
|
101
|
+
['forkit-connect inbox', 'Review what should become a Passport'],
|
|
102
|
+
['forkit-connect runtime status', 'Check runtime connection and signal posture'],
|
|
103
|
+
];
|
|
104
|
+
const EVERYDAY_COMMANDS = [
|
|
105
|
+
['forkit-connect status', 'One-line account, device, queue, and scope health'],
|
|
106
|
+
['forkit-connect start', 'Open the guided local launcher'],
|
|
107
|
+
['forkit-connect sync', 'Flush queued metadata and lifecycle evidence'],
|
|
108
|
+
['forkit-connect doctor', 'Diagnose local setup issues'],
|
|
109
|
+
];
|
|
96
110
|
const ADVANCED_COMMAND_GROUPS = [
|
|
97
111
|
['connect', 'Model connection, runtime review, and handoff utilities'],
|
|
98
112
|
['runtime', 'Repo-scoped runtime observation and journaling utilities'],
|
|
@@ -117,27 +131,32 @@ const ADVANCED_COMMAND_GROUPS = [
|
|
|
117
131
|
['notify', 'Notification preview and delivery controls'],
|
|
118
132
|
];
|
|
119
133
|
function usage() {
|
|
120
|
-
printCliHeader('CLI', '
|
|
121
|
-
console.log(cliKeyLine('
|
|
122
|
-
console.log(cliKeyLine('
|
|
123
|
-
console.log(cliKeyLine('
|
|
124
|
-
printCliSection('
|
|
125
|
-
for (const [command, description] of
|
|
126
|
-
console.log(
|
|
134
|
+
printCliHeader('CLI', 'Local AI runtime passporting without copying model data.');
|
|
135
|
+
console.log(cliKeyLine('best first run', 'forkit-connect login'));
|
|
136
|
+
console.log(cliKeyLine('privacy model', 'metadata only; secrets stay local'));
|
|
137
|
+
console.log(cliKeyLine('advanced map', 'forkit-connect --advanced-help'));
|
|
138
|
+
printCliSection('Start Here');
|
|
139
|
+
for (const [command, description] of START_HERE_COMMANDS) {
|
|
140
|
+
console.log(cliCommandLine(command, description));
|
|
141
|
+
}
|
|
142
|
+
printCliSection('Daily Ops');
|
|
143
|
+
for (const [command, description] of EVERYDAY_COMMANDS) {
|
|
144
|
+
console.log(cliCommandLine(command, description));
|
|
127
145
|
}
|
|
128
146
|
printCliSection('Flags');
|
|
129
147
|
console.log(cliKeyLine('--json', 'Machine-readable output when supported'));
|
|
130
|
-
console.log(cliKeyLine('--
|
|
131
|
-
console.log(cliKeyLine('--model', 'Model name used by register'));
|
|
132
|
-
console.log(cliKeyLine('--entrypoint', 'Relative project path used by runtime register'));
|
|
148
|
+
console.log(cliKeyLine('--version', 'Print the Forkit Connect CLI version'));
|
|
133
149
|
console.log(cliKeyLine('--dry-run', 'Show inferred runtime payload without creating it'));
|
|
134
|
-
console.log(cliKeyLine('--no-browser', 'Do not auto-open browser verification during login'));
|
|
135
150
|
console.log(cliKeyLine('--plain', 'Disable the interactive terminal table surface'));
|
|
136
|
-
console.log(cliKeyLine('--advanced-help', 'Show
|
|
151
|
+
console.log(cliKeyLine('--advanced-help', 'Show the full engineering command map'));
|
|
137
152
|
}
|
|
138
153
|
function advancedUsage() {
|
|
139
|
-
|
|
140
|
-
printCliSection('
|
|
154
|
+
printCliHeader('Advanced CLI', 'Full engineering map for automation, C2, and release operations.');
|
|
155
|
+
printCliSection('Public Commands');
|
|
156
|
+
for (const [command, description] of PUBLIC_COMMANDS) {
|
|
157
|
+
console.log(cliKeyLine(command, description));
|
|
158
|
+
}
|
|
159
|
+
printCliSection('Advanced Routes');
|
|
141
160
|
console.log(cliKeyLine('connect', 'forkit-connect connect <modelNameOrDiscoveryHash>'));
|
|
142
161
|
console.log(cliKeyLine('connect', 'forkit-connect connect <start|init|status|inbox|services|permissions|handoff|evolution review|runtime review|runtime status>'));
|
|
143
162
|
console.log(cliKeyLine('targets', 'forkit-connect runtime target <add|list|remove|status>'));
|
|
@@ -877,6 +896,9 @@ function cliTag(label, tone = 'muted') {
|
|
|
877
896
|
function cliKeyLine(label, value) {
|
|
878
897
|
return ` ${cliDim(`${label}`.padEnd(CLI_LABEL_WIDTH, ' '))} ${value}`;
|
|
879
898
|
}
|
|
899
|
+
function cliCommandLine(command, value) {
|
|
900
|
+
return ` ${cliDim(command.padEnd(34, ' '))} ${value}`;
|
|
901
|
+
}
|
|
880
902
|
function printCliHeader(title, subtitle) {
|
|
881
903
|
console.log(`[forkit-connect] ${cliBold(title)}`);
|
|
882
904
|
if (subtitle) {
|
|
@@ -2609,6 +2631,10 @@ async function run() {
|
|
|
2609
2631
|
showUsage();
|
|
2610
2632
|
return;
|
|
2611
2633
|
}
|
|
2634
|
+
if (command === 'version' || command === '--version' || command === '-v') {
|
|
2635
|
+
console.log((0, update_1.getCurrentConnectVersion)());
|
|
2636
|
+
return;
|
|
2637
|
+
}
|
|
2612
2638
|
if (isHelpCommand(command)) {
|
|
2613
2639
|
showUsage();
|
|
2614
2640
|
return;
|
|
@@ -2754,6 +2780,37 @@ async function run() {
|
|
|
2754
2780
|
return;
|
|
2755
2781
|
}
|
|
2756
2782
|
const result = await service.runDiscoveryCycle();
|
|
2783
|
+
const heartbeatGaid = getArg('--heartbeat-gaid');
|
|
2784
|
+
const heartbeatKey = getArg('--heartbeat-key');
|
|
2785
|
+
let heartbeatQueueId = null;
|
|
2786
|
+
if (heartbeatGaid && heartbeatKey) {
|
|
2787
|
+
heartbeatQueueId = service.queueHeartbeatRuntimeSignal(heartbeatGaid, heartbeatKey);
|
|
2788
|
+
}
|
|
2789
|
+
if (hasFlag('--json')) {
|
|
2790
|
+
printJson({
|
|
2791
|
+
ok: result.ok,
|
|
2792
|
+
message: result.message,
|
|
2793
|
+
discovery_mode: result.discoveryMode,
|
|
2794
|
+
runtimes: result.runtimes,
|
|
2795
|
+
models: result.models,
|
|
2796
|
+
counts: {
|
|
2797
|
+
new_models: result.newModels,
|
|
2798
|
+
already_known_models: result.alreadyKnownModels,
|
|
2799
|
+
duplicate_discoveries_skipped: result.duplicateDiscoveriesSkipped,
|
|
2800
|
+
},
|
|
2801
|
+
summary: result.summary,
|
|
2802
|
+
queue: result.queue,
|
|
2803
|
+
sync: result.sync,
|
|
2804
|
+
heartbeat_queue_id: heartbeatQueueId,
|
|
2805
|
+
next_action: result.ok
|
|
2806
|
+
? null
|
|
2807
|
+
: 'Start Ollama, LM Studio, an OpenAI-compatible local server, or add local model directories, then rerun scan.',
|
|
2808
|
+
});
|
|
2809
|
+
if (!result.ok) {
|
|
2810
|
+
process.exitCode = 0;
|
|
2811
|
+
}
|
|
2812
|
+
return;
|
|
2813
|
+
}
|
|
2757
2814
|
console.log(result.message);
|
|
2758
2815
|
for (const runtime of result.runtimes) {
|
|
2759
2816
|
const runtimeStatus = runtime.ok ? 'detected' : 'unavailable';
|
|
@@ -2767,13 +2824,8 @@ async function run() {
|
|
|
2767
2824
|
console.log(`[forkit-connect] Detected new=${result.newModels} already_known=${result.alreadyKnownModels} duplicates_skipped=${result.duplicateDiscoveriesSkipped}`);
|
|
2768
2825
|
printDiscoverySummary(result.summary);
|
|
2769
2826
|
console.log(`[forkit-connect] Queue queued=${result.queue.queued} skipped_pending=${result.queue.skippedPending} skipped_bound=${result.queue.skippedBound} skipped_duplicates=${result.queue.skippedDuplicate}`);
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
if (heartbeatGaid && heartbeatKey) {
|
|
2773
|
-
const queueId = service.queueHeartbeatRuntimeSignal(heartbeatGaid, heartbeatKey);
|
|
2774
|
-
if (queueId) {
|
|
2775
|
-
console.log(`[forkit-connect] Queued heartbeat runtime signal: ${queueId}`);
|
|
2776
|
-
}
|
|
2827
|
+
if (heartbeatQueueId) {
|
|
2828
|
+
console.log(`[forkit-connect] Queued heartbeat runtime signal: ${heartbeatQueueId}`);
|
|
2777
2829
|
}
|
|
2778
2830
|
console.log(`[forkit-connect] Queue processed=${result.sync.processed} succeeded=${result.sync.succeeded} failed=${result.sync.failed}`);
|
|
2779
2831
|
if (!result.ok) {
|
|
@@ -2879,11 +2931,12 @@ async function run() {
|
|
|
2879
2931
|
await withTimeout(service.prewarmSmartRegistrationInbox(), 1800, undefined);
|
|
2880
2932
|
printSessionExportFallback(polled.body.connect_access_token);
|
|
2881
2933
|
const displayName = getSessionDisplayName(polled.body.connect_access_token);
|
|
2882
|
-
console.
|
|
2883
|
-
? `[forkit-connect]
|
|
2884
|
-
: '[forkit-connect]
|
|
2885
|
-
|
|
2886
|
-
|
|
2934
|
+
console.error(displayName
|
|
2935
|
+
? `[forkit-connect] Approval reached Forkit.dev for ${displayName}, but this CLI process could not persist the session.`
|
|
2936
|
+
: '[forkit-connect] Approval reached Forkit.dev, but this CLI process could not persist the session.');
|
|
2937
|
+
console.error('[forkit-connect] Login is not complete. Rerun `forkit-connect login` from a desktop/keychain session or fix secure storage first.');
|
|
2938
|
+
process.exitCode = 2;
|
|
2939
|
+
return false;
|
|
2887
2940
|
}
|
|
2888
2941
|
throw error;
|
|
2889
2942
|
}
|
|
@@ -6648,6 +6701,17 @@ async function run() {
|
|
|
6648
6701
|
}
|
|
6649
6702
|
if (command === 'doctor') {
|
|
6650
6703
|
const checks = await service.runDoctorChecks();
|
|
6704
|
+
if (hasFlag('--json')) {
|
|
6705
|
+
printJson({
|
|
6706
|
+
ok: !checks.some((check) => check.status === 'FAIL'),
|
|
6707
|
+
generated_at: new Date().toISOString(),
|
|
6708
|
+
checks,
|
|
6709
|
+
});
|
|
6710
|
+
if (checks.some((check) => check.status === 'FAIL')) {
|
|
6711
|
+
process.exitCode = 2;
|
|
6712
|
+
}
|
|
6713
|
+
return;
|
|
6714
|
+
}
|
|
6651
6715
|
for (const check of checks) {
|
|
6652
6716
|
console.log(`[${check.status}] ${check.name}: ${check.details}`);
|
|
6653
6717
|
}
|
package/dist/v1/update.d.ts
CHANGED
|
@@ -19,7 +19,9 @@ export interface ReleaseManifest {
|
|
|
19
19
|
export interface ReleaseCheckSuccess {
|
|
20
20
|
ok: true;
|
|
21
21
|
manifestUrl: string;
|
|
22
|
+
npmLatestUrl: string;
|
|
22
23
|
currentVersion: string;
|
|
24
|
+
cliLatestVersion: string | null;
|
|
23
25
|
manifest: ReleaseManifest;
|
|
24
26
|
availability: 'up-to-date' | 'update-available' | 'required-update';
|
|
25
27
|
downloadUrl: string | null;
|
|
@@ -27,12 +29,14 @@ export interface ReleaseCheckSuccess {
|
|
|
27
29
|
export interface ReleaseCheckFailure {
|
|
28
30
|
ok: false;
|
|
29
31
|
manifestUrl: string;
|
|
32
|
+
npmLatestUrl: string;
|
|
30
33
|
currentVersion: string;
|
|
31
34
|
error: string;
|
|
32
35
|
}
|
|
33
36
|
export type ReleaseCheckResult = ReleaseCheckSuccess | ReleaseCheckFailure;
|
|
34
37
|
export declare function getCurrentConnectVersion(): string;
|
|
35
38
|
export declare function getReleaseManifestUrl(): string;
|
|
36
|
-
export declare function
|
|
39
|
+
export declare function getNpmLatestUrl(): string;
|
|
40
|
+
export declare function checkForUpdates(manifestUrl?: string, npmLatestUrl?: string): Promise<ReleaseCheckResult>;
|
|
37
41
|
export declare function formatUpdateCheckLines(result: ReleaseCheckResult): string[];
|
|
38
42
|
//# sourceMappingURL=update.d.ts.map
|
package/dist/v1/update.js
CHANGED
|
@@ -5,12 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getCurrentConnectVersion = getCurrentConnectVersion;
|
|
7
7
|
exports.getReleaseManifestUrl = getReleaseManifestUrl;
|
|
8
|
+
exports.getNpmLatestUrl = getNpmLatestUrl;
|
|
8
9
|
exports.checkForUpdates = checkForUpdates;
|
|
9
10
|
exports.formatUpdateCheckLines = formatUpdateCheckLines;
|
|
10
11
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
12
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
13
|
const node_url_1 = require("node:url");
|
|
13
14
|
const DEFAULT_RELEASE_MANIFEST_URL = process.env.FORKIT_CONNECT_RELEASE_MANIFEST_URL ?? 'https://forkit.dev/connect/releases/latest.json';
|
|
15
|
+
const DEFAULT_NPM_LATEST_URL = process.env.FORKIT_CONNECT_NPM_LATEST_URL ?? 'https://registry.npmjs.org/forkit-connect/latest';
|
|
14
16
|
function readPackageJsonVersion() {
|
|
15
17
|
try {
|
|
16
18
|
const packageJsonPath = node_path_1.default.resolve(__dirname, '..', '..', 'package.json');
|
|
@@ -64,15 +66,41 @@ function pickDownloadUrl(downloads) {
|
|
|
64
66
|
}
|
|
65
67
|
return downloads.linuxAppImage?.url || downloads.linuxDeb?.url || null;
|
|
66
68
|
}
|
|
69
|
+
function isNpmLatestResponse(value) {
|
|
70
|
+
return !!value
|
|
71
|
+
&& typeof value === 'object'
|
|
72
|
+
&& typeof value.version === 'string'
|
|
73
|
+
&& Boolean(String(value.version).trim());
|
|
74
|
+
}
|
|
75
|
+
async function fetchNpmLatestVersion(npmLatestUrl = DEFAULT_NPM_LATEST_URL) {
|
|
76
|
+
if (process.env.FORKIT_CONNECT_SKIP_NPM_UPDATE_CHECK === '1') {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const response = await fetch(npmLatestUrl, {
|
|
80
|
+
method: 'GET',
|
|
81
|
+
headers: {
|
|
82
|
+
Accept: 'application/json',
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const body = await response.json();
|
|
89
|
+
return isNpmLatestResponse(body) ? body.version.trim() : null;
|
|
90
|
+
}
|
|
67
91
|
function getCurrentConnectVersion() {
|
|
68
92
|
return readPackageJsonVersion();
|
|
69
93
|
}
|
|
70
94
|
function getReleaseManifestUrl() {
|
|
71
95
|
return DEFAULT_RELEASE_MANIFEST_URL;
|
|
72
96
|
}
|
|
73
|
-
|
|
97
|
+
function getNpmLatestUrl() {
|
|
98
|
+
return DEFAULT_NPM_LATEST_URL;
|
|
99
|
+
}
|
|
100
|
+
async function checkForUpdates(manifestUrl = getReleaseManifestUrl(), npmLatestUrl = getNpmLatestUrl()) {
|
|
74
101
|
const currentVersion = getCurrentConnectVersion();
|
|
75
102
|
try {
|
|
103
|
+
const cliLatestVersion = await fetchNpmLatestVersion(npmLatestUrl).catch(() => null);
|
|
76
104
|
if (manifestUrl.startsWith('file://')) {
|
|
77
105
|
const manifestPath = (0, node_url_1.fileURLToPath)(manifestUrl);
|
|
78
106
|
const raw = await node_fs_1.default.promises.readFile(manifestPath, 'utf8');
|
|
@@ -81,12 +109,15 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
81
109
|
return {
|
|
82
110
|
ok: false,
|
|
83
111
|
manifestUrl,
|
|
112
|
+
npmLatestUrl,
|
|
84
113
|
currentVersion,
|
|
85
114
|
error: 'invalid_manifest',
|
|
86
115
|
};
|
|
87
116
|
}
|
|
88
117
|
const minimumSupportedComparison = compareVersions(currentVersion, body.minimumSupportedVersion);
|
|
89
|
-
const latestComparison =
|
|
118
|
+
const latestComparison = cliLatestVersion
|
|
119
|
+
? compareVersions(currentVersion, cliLatestVersion)
|
|
120
|
+
: compareVersions(currentVersion, body.latestVersion);
|
|
90
121
|
const availability = minimumSupportedComparison < 0
|
|
91
122
|
? 'required-update'
|
|
92
123
|
: latestComparison < 0
|
|
@@ -95,7 +126,9 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
95
126
|
return {
|
|
96
127
|
ok: true,
|
|
97
128
|
manifestUrl,
|
|
129
|
+
npmLatestUrl,
|
|
98
130
|
currentVersion,
|
|
131
|
+
cliLatestVersion,
|
|
99
132
|
manifest: body,
|
|
100
133
|
availability,
|
|
101
134
|
downloadUrl: pickDownloadUrl(body.downloads),
|
|
@@ -111,6 +144,7 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
111
144
|
return {
|
|
112
145
|
ok: false,
|
|
113
146
|
manifestUrl,
|
|
147
|
+
npmLatestUrl,
|
|
114
148
|
currentVersion,
|
|
115
149
|
error: `manifest_http_${response.status}`,
|
|
116
150
|
};
|
|
@@ -120,12 +154,15 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
120
154
|
return {
|
|
121
155
|
ok: false,
|
|
122
156
|
manifestUrl,
|
|
157
|
+
npmLatestUrl,
|
|
123
158
|
currentVersion,
|
|
124
159
|
error: 'invalid_manifest',
|
|
125
160
|
};
|
|
126
161
|
}
|
|
127
162
|
const minimumSupportedComparison = compareVersions(currentVersion, body.minimumSupportedVersion);
|
|
128
|
-
const latestComparison =
|
|
163
|
+
const latestComparison = cliLatestVersion
|
|
164
|
+
? compareVersions(currentVersion, cliLatestVersion)
|
|
165
|
+
: compareVersions(currentVersion, body.latestVersion);
|
|
129
166
|
const availability = minimumSupportedComparison < 0
|
|
130
167
|
? 'required-update'
|
|
131
168
|
: latestComparison < 0
|
|
@@ -134,7 +171,9 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
134
171
|
return {
|
|
135
172
|
ok: true,
|
|
136
173
|
manifestUrl,
|
|
174
|
+
npmLatestUrl,
|
|
137
175
|
currentVersion,
|
|
176
|
+
cliLatestVersion,
|
|
138
177
|
manifest: body,
|
|
139
178
|
availability,
|
|
140
179
|
downloadUrl: pickDownloadUrl(body.downloads),
|
|
@@ -144,6 +183,7 @@ async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
|
|
|
144
183
|
return {
|
|
145
184
|
ok: false,
|
|
146
185
|
manifestUrl,
|
|
186
|
+
npmLatestUrl,
|
|
147
187
|
currentVersion,
|
|
148
188
|
error: error instanceof Error ? error.message : 'manifest_fetch_failed',
|
|
149
189
|
};
|
|
@@ -163,16 +203,20 @@ function formatUpdateCheckLines(result) {
|
|
|
163
203
|
lines.push('This version is no longer supported.');
|
|
164
204
|
}
|
|
165
205
|
else if (result.availability === 'update-available') {
|
|
166
|
-
lines.push('
|
|
206
|
+
lines.push('CLI update available.');
|
|
167
207
|
}
|
|
168
208
|
else {
|
|
169
|
-
lines.push('Forkit Connect is up to date.');
|
|
209
|
+
lines.push('Forkit Connect CLI is up to date.');
|
|
170
210
|
}
|
|
171
|
-
lines.push(`Current version: ${result.currentVersion}`);
|
|
172
|
-
lines.push(`Latest version: ${result.
|
|
211
|
+
lines.push(`Current CLI version: ${result.currentVersion}`);
|
|
212
|
+
lines.push(`Latest CLI version: ${result.cliLatestVersion || 'unavailable'}`);
|
|
213
|
+
lines.push(`Desktop installer latest: ${result.manifest.latestVersion}`);
|
|
173
214
|
if (result.availability !== 'up-to-date') {
|
|
174
|
-
if (result.
|
|
175
|
-
lines.push(
|
|
215
|
+
if (result.cliLatestVersion && compareVersions(result.currentVersion, result.cliLatestVersion) < 0) {
|
|
216
|
+
lines.push('Update command: npm install -g forkit-connect@latest');
|
|
217
|
+
}
|
|
218
|
+
else if (result.downloadUrl) {
|
|
219
|
+
lines.push(`Desktop download: ${result.downloadUrl}`);
|
|
176
220
|
}
|
|
177
221
|
lines.push(`Release notes: ${result.manifest.releaseNotesUrl}`);
|
|
178
222
|
if (result.manifest.updateMessage) {
|