forkit-connect 0.1.28 → 0.1.29

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 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'],
@@ -127,6 +128,7 @@ function usage() {
127
128
  }
128
129
  printCliSection('Flags');
129
130
  console.log(cliKeyLine('--json', 'Machine-readable output when supported'));
131
+ console.log(cliKeyLine('--version', 'Print the Forkit Connect CLI version'));
130
132
  console.log(cliKeyLine('--all-ready', 'Register every ready local model in the current scope'));
131
133
  console.log(cliKeyLine('--model', 'Model name used by register'));
132
134
  console.log(cliKeyLine('--entrypoint', 'Relative project path used by runtime register'));
@@ -2609,6 +2611,10 @@ async function run() {
2609
2611
  showUsage();
2610
2612
  return;
2611
2613
  }
2614
+ if (command === 'version' || command === '--version' || command === '-v') {
2615
+ console.log((0, update_1.getCurrentConnectVersion)());
2616
+ return;
2617
+ }
2612
2618
  if (isHelpCommand(command)) {
2613
2619
  showUsage();
2614
2620
  return;
@@ -2754,6 +2760,37 @@ async function run() {
2754
2760
  return;
2755
2761
  }
2756
2762
  const result = await service.runDiscoveryCycle();
2763
+ const heartbeatGaid = getArg('--heartbeat-gaid');
2764
+ const heartbeatKey = getArg('--heartbeat-key');
2765
+ let heartbeatQueueId = null;
2766
+ if (heartbeatGaid && heartbeatKey) {
2767
+ heartbeatQueueId = service.queueHeartbeatRuntimeSignal(heartbeatGaid, heartbeatKey);
2768
+ }
2769
+ if (hasFlag('--json')) {
2770
+ printJson({
2771
+ ok: result.ok,
2772
+ message: result.message,
2773
+ discovery_mode: result.discoveryMode,
2774
+ runtimes: result.runtimes,
2775
+ models: result.models,
2776
+ counts: {
2777
+ new_models: result.newModels,
2778
+ already_known_models: result.alreadyKnownModels,
2779
+ duplicate_discoveries_skipped: result.duplicateDiscoveriesSkipped,
2780
+ },
2781
+ summary: result.summary,
2782
+ queue: result.queue,
2783
+ sync: result.sync,
2784
+ heartbeat_queue_id: heartbeatQueueId,
2785
+ next_action: result.ok
2786
+ ? null
2787
+ : 'Start Ollama, LM Studio, an OpenAI-compatible local server, or add local model directories, then rerun scan.',
2788
+ });
2789
+ if (!result.ok) {
2790
+ process.exitCode = 0;
2791
+ }
2792
+ return;
2793
+ }
2757
2794
  console.log(result.message);
2758
2795
  for (const runtime of result.runtimes) {
2759
2796
  const runtimeStatus = runtime.ok ? 'detected' : 'unavailable';
@@ -2767,13 +2804,8 @@ async function run() {
2767
2804
  console.log(`[forkit-connect] Detected new=${result.newModels} already_known=${result.alreadyKnownModels} duplicates_skipped=${result.duplicateDiscoveriesSkipped}`);
2768
2805
  printDiscoverySummary(result.summary);
2769
2806
  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
- const heartbeatGaid = getArg('--heartbeat-gaid');
2771
- const heartbeatKey = getArg('--heartbeat-key');
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
- }
2807
+ if (heartbeatQueueId) {
2808
+ console.log(`[forkit-connect] Queued heartbeat runtime signal: ${heartbeatQueueId}`);
2777
2809
  }
2778
2810
  console.log(`[forkit-connect] Queue processed=${result.sync.processed} succeeded=${result.sync.succeeded} failed=${result.sync.failed}`);
2779
2811
  if (!result.ok) {
@@ -2879,11 +2911,12 @@ async function run() {
2879
2911
  await withTimeout(service.prewarmSmartRegistrationInbox(), 1800, undefined);
2880
2912
  printSessionExportFallback(polled.body.connect_access_token);
2881
2913
  const displayName = getSessionDisplayName(polled.body.connect_access_token);
2882
- console.log(displayName
2883
- ? `[forkit-connect] Welcome, ${displayName}. Continuing with an environment-backed session for this run.`
2884
- : '[forkit-connect] Continuing with an environment-backed session for this run.');
2885
- process.exitCode = 0;
2886
- return true;
2914
+ console.error(displayName
2915
+ ? `[forkit-connect] Approval reached Forkit.dev for ${displayName}, but this CLI process could not persist the session.`
2916
+ : '[forkit-connect] Approval reached Forkit.dev, but this CLI process could not persist the session.');
2917
+ console.error('[forkit-connect] Login is not complete. Rerun `forkit-connect login` from a desktop/keychain session or fix secure storage first.');
2918
+ process.exitCode = 2;
2919
+ return false;
2887
2920
  }
2888
2921
  throw error;
2889
2922
  }
@@ -6648,6 +6681,17 @@ async function run() {
6648
6681
  }
6649
6682
  if (command === 'doctor') {
6650
6683
  const checks = await service.runDoctorChecks();
6684
+ if (hasFlag('--json')) {
6685
+ printJson({
6686
+ ok: !checks.some((check) => check.status === 'FAIL'),
6687
+ generated_at: new Date().toISOString(),
6688
+ checks,
6689
+ });
6690
+ if (checks.some((check) => check.status === 'FAIL')) {
6691
+ process.exitCode = 2;
6692
+ }
6693
+ return;
6694
+ }
6651
6695
  for (const check of checks) {
6652
6696
  console.log(`[${check.status}] ${check.name}: ${check.details}`);
6653
6697
  }
@@ -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 checkForUpdates(manifestUrl?: string): Promise<ReleaseCheckResult>;
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
- async function checkForUpdates(manifestUrl = getReleaseManifestUrl()) {
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 = compareVersions(currentVersion, body.latestVersion);
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 = compareVersions(currentVersion, body.latestVersion);
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('Update available.');
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.manifest.latestVersion}`);
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.downloadUrl) {
175
- lines.push(`Download: ${result.downloadUrl}`);
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forkit-connect",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "Forkit Connect Local Engine - The Global AI Governance Fabric",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",