forkit-connect 0.1.22 → 0.1.24

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/README.md CHANGED
@@ -6,7 +6,8 @@ Naming convention:
6
6
 
7
7
  - Product name: Forkit Connect
8
8
  - Command name: `forkit-connect`
9
- - Package name: `@forkit/connect`
9
+ - Published package name: `forkit-connect`
10
+ - Workspace dependency alias: `@forkit/connect`
10
11
 
11
12
  ## Install Surface
12
13
 
@@ -60,10 +61,13 @@ If `~/.local/bin` is already on your `PATH`, the command is immediately accessib
60
61
  - `forkit-connect login` — link this device to Forkit.dev with the device flow
61
62
  - `forkit-connect scan` — discover local runtimes and AI models
62
63
  - `forkit-connect inbox` — review the Smart Registration Inbox
64
+ - `forkit-connect connect <modelNameOrDiscoveryHash>` — prepare or sync a passport draft for a detected model
63
65
  - `forkit-connect runtime register` — register or reuse the current repo/worktree as a governed runtime
64
66
  - `forkit-connect runtime observe --gaid <gaid>` — emit a repo-scoped runtime journal for the current runtime target
65
67
  - `forkit-connect status` — show public Connect readiness status
66
68
  - `forkit-connect changes` — view collected local evidence, runtime signal history, and pending sync items
69
+ - `forkit-connect doctor` — run local environment, secure-storage, backend-session, and account checks
70
+ - `forkit-connect update-check` — inspect release metadata without enabling auto-update
67
71
  - `forkit-connect start` — start the local daemon loop
68
72
  - `forkit-connect stop` — stop the background daemon without deleting local state
69
73
  - `forkit-connect uninstall` — preview a cautious uninstall plan and write local backup logs
@@ -72,7 +76,7 @@ If `~/.local/bin` is already on your `PATH`, the command is immediately accessib
72
76
 
73
77
  ## Advanced Commands
74
78
 
75
- Advanced flows remain available under the same binary, including `connect`, `review`, `daemon`, `config`, `pulse`, `c2`, `train`, `agent`, notification utilities, and runtime target management.
79
+ Advanced flows remain available under the same binary, including `review`, `daemon`, `config`, `pulse`, `c2`, `train`, `agent`, notification utilities, and runtime target management.
76
80
 
77
81
  Runtime registration notes:
78
82
 
@@ -117,7 +121,7 @@ Then install the generated tarball into a clean directory:
117
121
  mkdir -p /tmp/forkit-connect-smoke
118
122
  cd /tmp/forkit-connect-smoke
119
123
  npm init -y
120
- npm install /absolute/path/to/forkit-connect-0.1.1.tgz
124
+ npm install /absolute/path/to/forkit-connect-0.1.24.tgz
121
125
  npx forkit-connect --help
122
126
  npx forkit-connect status
123
127
  npx forkit-connect inbox
package/dist/cli.js CHANGED
@@ -253,10 +253,10 @@ function printDeviceLoginInstructions(start) {
253
253
  }
254
254
  function printSessionExportFallback(token) {
255
255
  void token;
256
- console.log('[forkit-connect] Approval succeeded, but secure credential storage is unavailable in this Linux session.');
257
- console.log('[forkit-connect] Forkit Connect can keep using this approved session in the current interactive run.');
258
- console.log('[forkit-connect] For persistent login, install libsecret-tools and run forkit-connect login again.');
259
- console.log('[forkit-connect] Headless automation may pass FORKIT_CONNECT_SESSION_REF explicitly, but Connect will not print session tokens.');
256
+ console.log('[forkit-connect] Approval succeeded, but secure credential storage is unavailable or timed out on this machine.');
257
+ console.log('[forkit-connect] Forkit Connect will not print session tokens. Persistent login requires working secure storage.');
258
+ console.log('[forkit-connect] macOS: unlock Keychain and run forkit-connect login again. Linux: install libsecret-tools and run inside a DBus user session.');
259
+ console.log('[forkit-connect] Headless automation may pass FORKIT_CONNECT_SESSION_REF explicitly from a secret manager.');
260
260
  }
261
261
  function hasLinuxGuiSession() {
262
262
  if (process.platform !== 'linux') {
@@ -935,7 +935,7 @@ function formatCliScopeLabel(workspaceId, projectId) {
935
935
  if (workspace) {
936
936
  return `${shortId(workspace)} / project needed`;
937
937
  }
938
- return 'solo / no workspace';
938
+ return 'personal device / workspace not selected';
939
939
  }
940
940
  function summarizeReviewQueueCounts(values) {
941
941
  const parts = [
@@ -2637,7 +2637,12 @@ async function run() {
2637
2637
  const overview = withSmartInboxSnapshotCounts(service.getConnectStatusOverview({ includeInbox: false }));
2638
2638
  const localScopeCached = Boolean(String(overview.workspace_id || '').trim() || String(overview.project_id || '').trim());
2639
2639
  const displayOverview = accountTrusted
2640
- ? overview
2640
+ ? {
2641
+ ...overview,
2642
+ lifecycle_note: !localScopeCached && overview.device_paired
2643
+ ? 'Account connected. Personal scanning works; select workspace/project later for C2.'
2644
+ : overview.lifecycle_note,
2645
+ }
2641
2646
  : {
2642
2647
  ...overview,
2643
2648
  workspace_id: null,
@@ -2767,7 +2772,8 @@ async function run() {
2767
2772
  }
2768
2773
  console.log(`[forkit-connect] Queue processed=${result.sync.processed} succeeded=${result.sync.succeeded} failed=${result.sync.failed}`);
2769
2774
  if (!result.ok) {
2770
- process.exitCode = 2;
2775
+ console.log('[forkit-connect] No runtime passport was created. Start Ollama, LM Studio, an OpenAI-compatible local server, or add local model directories, then rerun scan.');
2776
+ process.exitCode = 0;
2771
2777
  }
2772
2778
  };
2773
2779
  const runPublicUpdateCheck = async () => {
@@ -20,6 +20,7 @@ exports.ConnectCredentialStoreError = ConnectCredentialStoreError;
20
20
  const SERVICE_BASE_NAME = 'ForkitConnect';
21
21
  const LEGACY_SERVICE_NAME = SERVICE_BASE_NAME;
22
22
  const LINUX_SECRET_TOOL_TIMEOUT_MS = 1200;
23
+ const MACOS_SECURITY_TIMEOUT_MS = Number(process.env.FORKIT_CONNECT_MACOS_SECURITY_TIMEOUT_MS || 15000);
23
24
  function nowIso() {
24
25
  return new Date().toISOString();
25
26
  }
@@ -187,6 +188,7 @@ class MacOsKeychainBackend {
187
188
  '-w',
188
189
  ], {
189
190
  encoding: 'utf8',
191
+ timeout: MACOS_SECURITY_TIMEOUT_MS,
190
192
  });
191
193
  if (result.error) {
192
194
  throw new ConnectCredentialStoreError('secure_storage_read_failed', `Forkit Connect could not read secure credentials from macOS Keychain: ${result.error.message}`);
@@ -211,6 +213,7 @@ class MacOsKeychainBackend {
211
213
  value,
212
214
  ], {
213
215
  encoding: 'utf8',
216
+ timeout: MACOS_SECURITY_TIMEOUT_MS,
214
217
  });
215
218
  if (result.error) {
216
219
  throw new ConnectCredentialStoreError('secure_storage_write_failed', `Forkit Connect could not write secure credentials to macOS Keychain: ${result.error.message}`);
@@ -229,6 +232,7 @@ class MacOsKeychainBackend {
229
232
  account,
230
233
  ], {
231
234
  encoding: 'utf8',
235
+ timeout: MACOS_SECURITY_TIMEOUT_MS,
232
236
  });
233
237
  if (result.error) {
234
238
  throw new ConnectCredentialStoreError('secure_storage_delete_failed', `Forkit Connect could not remove secure credentials from macOS Keychain: ${result.error.message}`);
@@ -241,6 +245,7 @@ class MacOsKeychainBackend {
241
245
  getStatus() {
242
246
  const result = (0, node_child_process_1.spawnSync)('security', ['list-keychains'], {
243
247
  encoding: 'utf8',
248
+ timeout: MACOS_SECURITY_TIMEOUT_MS,
244
249
  });
245
250
  if (result.error) {
246
251
  return {
@@ -0,0 +1,23 @@
1
+ import { type ReleaseCheckResult } from './update';
2
+ export interface NativeShellStatus {
3
+ supported: boolean;
4
+ installed: boolean;
5
+ platform: 'macos' | 'windows' | 'linux';
6
+ installationPath: string | null;
7
+ trayAvailable: boolean;
8
+ startupAvailable: boolean;
9
+ directInstallerAvailable: boolean;
10
+ downloadUrl: string | null;
11
+ releaseNotesUrl: string | null;
12
+ note: string;
13
+ }
14
+ export interface NativeShellOpenResult {
15
+ ok: boolean;
16
+ opened: 'installed' | 'download';
17
+ installationPath: string | null;
18
+ downloadUrl: string | null;
19
+ message: string;
20
+ }
21
+ export declare function getNativeShellStatus(updateCheck?: ReleaseCheckResult): Promise<NativeShellStatus>;
22
+ export declare function openNativeShell(updateCheck?: ReleaseCheckResult): Promise<NativeShellOpenResult>;
23
+ //# sourceMappingURL=native-shell.d.ts.map
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getNativeShellStatus = getNativeShellStatus;
7
+ exports.openNativeShell = openNativeShell;
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_os_1 = __importDefault(require("node:os"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const node_child_process_1 = require("node:child_process");
12
+ const update_1 = require("./update");
13
+ const CONNECT_DESKTOP_FALLBACK_URL = 'https://www.forkit.dev/connect';
14
+ function normalizePlatform() {
15
+ if (process.platform === 'darwin')
16
+ return 'macos';
17
+ if (process.platform === 'win32')
18
+ return 'windows';
19
+ return 'linux';
20
+ }
21
+ function getCandidatePaths(platform) {
22
+ const home = node_os_1.default.homedir();
23
+ if (platform === 'macos') {
24
+ return [
25
+ '/Applications/Forkit Connect.app',
26
+ node_path_1.default.join(home, 'Applications', 'Forkit Connect.app'),
27
+ ];
28
+ }
29
+ if (platform === 'windows') {
30
+ const localAppData = process.env.LOCALAPPDATA || node_path_1.default.join(home, 'AppData', 'Local');
31
+ const programFiles = process.env.ProgramFiles || 'C:\\Program Files';
32
+ const programFilesX86 = process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)';
33
+ return [
34
+ node_path_1.default.join(localAppData, 'Programs', 'Forkit Connect', 'Forkit Connect.exe'),
35
+ node_path_1.default.join(programFiles, 'Forkit Connect', 'Forkit Connect.exe'),
36
+ node_path_1.default.join(programFilesX86, 'Forkit Connect', 'Forkit Connect.exe'),
37
+ ];
38
+ }
39
+ return [
40
+ node_path_1.default.join(home, '.local', 'bin', 'forkit-connect-desktop'),
41
+ node_path_1.default.join(home, '.local', 'share', 'Forkit Connect', 'Forkit Connect.AppImage'),
42
+ '/usr/local/bin/forkit-connect-desktop',
43
+ '/opt/Forkit Connect/forkit-connect-desktop',
44
+ ];
45
+ }
46
+ function findInstalledPath(platform) {
47
+ for (const candidate of getCandidatePaths(platform)) {
48
+ try {
49
+ if (node_fs_1.default.existsSync(candidate)) {
50
+ return candidate;
51
+ }
52
+ }
53
+ catch {
54
+ continue;
55
+ }
56
+ }
57
+ return null;
58
+ }
59
+ function parseVersion(version) {
60
+ const cleaned = String(version || '').trim().replace(/^v/i, '').split('-')[0] || '0.0.0';
61
+ const [major, minor, patch] = cleaned.split('.').map((value) => Number.parseInt(value || '0', 10));
62
+ return [major || 0, minor || 0, patch || 0];
63
+ }
64
+ function compareVersions(left, right) {
65
+ const [leftMajor, leftMinor, leftPatch] = parseVersion(left);
66
+ const [rightMajor, rightMinor, rightPatch] = parseVersion(right);
67
+ if (leftMajor !== rightMajor)
68
+ return leftMajor - rightMajor;
69
+ if (leftMinor !== rightMinor)
70
+ return leftMinor - rightMinor;
71
+ return leftPatch - rightPatch;
72
+ }
73
+ function buildDownloadUrl(updateCheck) {
74
+ if (!updateCheck.ok) {
75
+ return CONNECT_DESKTOP_FALLBACK_URL;
76
+ }
77
+ if (compareVersions(updateCheck.manifest.latestVersion, updateCheck.currentVersion) < 0) {
78
+ return CONNECT_DESKTOP_FALLBACK_URL;
79
+ }
80
+ return updateCheck.downloadUrl || updateCheck.manifest.releaseNotesUrl || CONNECT_DESKTOP_FALLBACK_URL;
81
+ }
82
+ function hasDirectInstaller(updateCheck) {
83
+ if (!updateCheck.ok)
84
+ return false;
85
+ if (compareVersions(updateCheck.manifest.latestVersion, updateCheck.currentVersion) < 0) {
86
+ return false;
87
+ }
88
+ return Boolean(updateCheck.downloadUrl);
89
+ }
90
+ function isInstallerOnlyRelease(updateCheck) {
91
+ if (!updateCheck.ok)
92
+ return false;
93
+ const manifest = updateCheck.manifest;
94
+ const integrity = manifest.integrity;
95
+ if (!integrity || typeof integrity !== 'object')
96
+ return false;
97
+ return integrity.installerOnly === true;
98
+ }
99
+ async function getNativeShellStatus(updateCheck) {
100
+ const platform = normalizePlatform();
101
+ const installationPath = findInstalledPath(platform);
102
+ const installed = Boolean(installationPath);
103
+ const resolvedUpdateCheck = updateCheck ?? await (0, update_1.checkForUpdates)();
104
+ const directInstallerAvailable = hasDirectInstaller(resolvedUpdateCheck);
105
+ const installerOnlyRelease = isInstallerOnlyRelease(resolvedUpdateCheck);
106
+ const downloadUrl = buildDownloadUrl(resolvedUpdateCheck);
107
+ const releaseNotesUrl = resolvedUpdateCheck.ok ? resolvedUpdateCheck.manifest.releaseNotesUrl : CONNECT_DESKTOP_FALLBACK_URL;
108
+ return {
109
+ supported: true,
110
+ installed,
111
+ platform,
112
+ installationPath,
113
+ trayAvailable: installed,
114
+ startupAvailable: installed,
115
+ directInstallerAvailable,
116
+ downloadUrl,
117
+ releaseNotesUrl,
118
+ note: installed
119
+ ? 'Desktop app installed. Tray or menu-bar controls and launch at sign-in are handled there.'
120
+ : installerOnlyRelease
121
+ ? 'Install the desktop app to get tray or menu-bar controls and launch at sign-in. In-app updates are not published for this release yet.'
122
+ : directInstallerAvailable
123
+ ? 'Install the desktop app to get tray or menu-bar controls, launch at sign-in, and in-app updates.'
124
+ : 'The desktop app installer is not published for this platform yet. Use the Connect downloads page for the current release.',
125
+ };
126
+ }
127
+ function spawnDetached(command, args, cwd) {
128
+ const child = (0, node_child_process_1.spawn)(command, args, {
129
+ detached: true,
130
+ stdio: 'ignore',
131
+ windowsHide: true,
132
+ ...(cwd ? { cwd } : {}),
133
+ });
134
+ child.unref();
135
+ }
136
+ function openInstalledShell(status) {
137
+ if (!status.installationPath) {
138
+ throw new Error('native_shell_missing');
139
+ }
140
+ if (status.platform === 'macos') {
141
+ spawnDetached('open', [status.installationPath]);
142
+ return;
143
+ }
144
+ if (status.platform === 'windows') {
145
+ spawnDetached(status.installationPath, [], node_path_1.default.dirname(status.installationPath));
146
+ return;
147
+ }
148
+ spawnDetached(status.installationPath, [], node_path_1.default.dirname(status.installationPath));
149
+ }
150
+ async function openNativeShell(updateCheck) {
151
+ const status = await getNativeShellStatus(updateCheck);
152
+ if (status.installed) {
153
+ openInstalledShell(status);
154
+ return {
155
+ ok: true,
156
+ opened: 'installed',
157
+ installationPath: status.installationPath,
158
+ downloadUrl: status.downloadUrl,
159
+ message: 'Opening the native Forkit Connect shell.',
160
+ };
161
+ }
162
+ return {
163
+ ok: false,
164
+ opened: 'download',
165
+ installationPath: null,
166
+ downloadUrl: status.downloadUrl,
167
+ message: 'Install the Forkit Connect desktop app to enable tray or menu-bar controls and launch at sign-in.',
168
+ };
169
+ }
170
+ //# sourceMappingURL=native-shell.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forkit-connect",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "Forkit Connect Local Engine - The Global AI Governance Fabric",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",