ticlawk 0.1.12-dev.0 → 0.1.12
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 +2 -4
- package/scripts/postinstall.mjs +6 -34
- package/src/adapters/ticlawk/api.mjs +17 -17
- package/src/adapters/ticlawk/index.mjs +15 -15
- package/src/core/config.mjs +4 -6
- package/src/core/daemon-install.mjs +0 -6
- package/src/core/uninstall.mjs +17 -27
- package/src/core/update-state.mjs +2 -2
- package/src/core/update.mjs +5 -15
- package/agent-freeway.mjs +0 -2
- package/bin/agent-freeway.mjs +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ticlawk",
|
|
3
|
-
"version": "0.1.12
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Connect local agent harnesses to Ticlawk, Telegram, and other mobile clients.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "ticlawk.mjs",
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
"./package.json": "./package.json"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"ticlawk": "bin/ticlawk.mjs"
|
|
13
|
-
"agent-freeway": "bin/agent-freeway.mjs"
|
|
12
|
+
"ticlawk": "bin/ticlawk.mjs"
|
|
14
13
|
},
|
|
15
14
|
"files": [
|
|
16
15
|
"assets/",
|
|
@@ -19,7 +18,6 @@
|
|
|
19
18
|
"src/",
|
|
20
19
|
"cc-watcher.mjs",
|
|
21
20
|
"ticlawk.mjs",
|
|
22
|
-
"agent-freeway.mjs",
|
|
23
21
|
"README.md",
|
|
24
22
|
"LICENSE"
|
|
25
23
|
],
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -1,36 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync, renameSync } from 'node:fs';
|
|
4
4
|
import { spawnSync } from 'node:child_process';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { dirname, join, resolve } from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
8
|
|
|
9
|
-
function shellQuote(value) {
|
|
10
|
-
return `'${String(value).replaceAll("'", "'\\''")}'`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function isLegacyManagedWrapper(path) {
|
|
14
|
-
try {
|
|
15
|
-
if (!existsSync(path)) return false;
|
|
16
|
-
if (!lstatSync(path).isFile()) return false;
|
|
17
|
-
const content = readFileSync(path, 'utf8');
|
|
18
|
-
return (
|
|
19
|
-
content.includes('node_modules/agent-freeway/bin/agent-freeway.mjs')
|
|
20
|
-
|| content.includes('node_modules/ticlawk/bin/ticlawk.mjs')
|
|
21
|
-
) && (content.includes('.local/share') || content.includes('INSTALL_ROOT'));
|
|
22
|
-
} catch {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
9
|
function runSetupReadiness(cliScript) {
|
|
28
10
|
const result = spawnSync(process.execPath, [cliScript, 'setup-readiness', '--ensure-daemon'], {
|
|
29
11
|
stdio: 'inherit',
|
|
30
12
|
env: {
|
|
31
13
|
...process.env,
|
|
32
14
|
TICLAWK_POSTINSTALL: '1',
|
|
33
|
-
AGENT_FREEWAY_POSTINSTALL: '1',
|
|
34
15
|
},
|
|
35
16
|
});
|
|
36
17
|
if (result.status !== 0) {
|
|
@@ -41,20 +22,11 @@ function runSetupReadiness(cliScript) {
|
|
|
41
22
|
if (process.env.npm_config_global === 'true') {
|
|
42
23
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
43
24
|
const cliScript = join(packageRoot, 'bin', 'ticlawk.mjs');
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
for (const wrapperPath of wrapperPaths) {
|
|
50
|
-
if (!isLegacyManagedWrapper(wrapperPath)) continue;
|
|
51
|
-
mkdirSync(dirname(wrapperPath), { recursive: true });
|
|
52
|
-
writeFileSync(wrapperPath, `#!/usr/bin/env bash
|
|
53
|
-
set -euo pipefail
|
|
54
|
-
exec ${shellQuote(process.execPath)} ${shellQuote(cliScript)} "$@"
|
|
55
|
-
`);
|
|
56
|
-
chmodSync(wrapperPath, 0o755);
|
|
57
|
-
console.log(`ticlawk: migrated legacy ${wrapperPath} to this npm install`);
|
|
25
|
+
const legacyHome = join(homedir(), '.agent-freeway');
|
|
26
|
+
const ticlawkHome = join(homedir(), '.ticlawk');
|
|
27
|
+
if (!existsSync(ticlawkHome) && existsSync(legacyHome)) {
|
|
28
|
+
renameSync(legacyHome, ticlawkHome);
|
|
29
|
+
console.log(`ticlawk: migrated ${legacyHome} to ${ticlawkHome}`);
|
|
58
30
|
}
|
|
59
31
|
|
|
60
32
|
runSetupReadiness(cliScript);
|
|
@@ -34,41 +34,41 @@ export function getConnectorWsUrl() {
|
|
|
34
34
|
// different agents to proceed concurrently.
|
|
35
35
|
const agentEventQueues = new Map(); // agentId -> Promise
|
|
36
36
|
|
|
37
|
-
export class
|
|
37
|
+
export class TiclawkUpdateRequiredError extends Error {
|
|
38
38
|
constructor(payload = {}) {
|
|
39
|
-
const currentVersion = payload.
|
|
40
|
-
const requiredVersion = payload.
|
|
39
|
+
const currentVersion = payload.current_ticlawk_version || payload.currentTiclawkVersion || getTiclawkVersion();
|
|
40
|
+
const requiredVersion = payload.required_ticlawk_version || payload.requiredTiclawkVersion || '';
|
|
41
41
|
super(`Ticlawk requires ticlawk >= ${requiredVersion || 'unknown'}, current version is ${currentVersion || 'unknown'}. Please update ticlawk.`);
|
|
42
|
-
this.name = '
|
|
43
|
-
this.code = '
|
|
42
|
+
this.name = 'TiclawkUpdateRequiredError';
|
|
43
|
+
this.code = 'ticlawk_update_required';
|
|
44
44
|
this.updateRequired = true;
|
|
45
45
|
this.status = 409;
|
|
46
46
|
this.statusCode = 409;
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
47
|
+
this.currentTiclawkVersion = currentVersion || null;
|
|
48
|
+
this.requiredTiclawkVersion = requiredVersion || null;
|
|
49
49
|
this.payload = payload;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function isUpdateRequiredError(err) {
|
|
54
|
-
return Boolean(err?.updateRequired || err?.code === '
|
|
54
|
+
return Boolean(err?.updateRequired || err?.code === 'ticlawk_update_required');
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function
|
|
57
|
+
export function getTiclawkVersion() {
|
|
58
58
|
return readPkgVersion() || '0.0.0';
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function
|
|
61
|
+
function withTiclawkVersion(body = {}) {
|
|
62
62
|
return {
|
|
63
63
|
...body,
|
|
64
|
-
|
|
64
|
+
ticlawk_version: getTiclawkVersion(),
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
function isUpdateRequiredPayload(payload) {
|
|
69
69
|
return Boolean(
|
|
70
|
-
payload?.error === '
|
|
71
|
-
|| payload?.code === '
|
|
70
|
+
payload?.error === 'ticlawk_update_required'
|
|
71
|
+
|| payload?.code === 'ticlawk_update_required'
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -95,7 +95,7 @@ async function apiFetch(path, opts = {}) {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
if (isUpdateRequiredPayload(parsed)) {
|
|
98
|
-
throw new
|
|
98
|
+
throw new TiclawkUpdateRequiredError(parsed);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
if (!res.ok) {
|
|
@@ -171,7 +171,7 @@ export async function getPendingMessages() {
|
|
|
171
171
|
export async function claimPendingMessages(hostId, limit = 5, excludedAgentIds = []) {
|
|
172
172
|
const { data } = await apiFetch('/api/messages/claim-pending', {
|
|
173
173
|
method: 'POST',
|
|
174
|
-
body: JSON.stringify(
|
|
174
|
+
body: JSON.stringify(withTiclawkVersion({
|
|
175
175
|
runtime_host_id: hostId,
|
|
176
176
|
limit,
|
|
177
177
|
excluded_agent_ids: excludedAgentIds,
|
|
@@ -190,7 +190,7 @@ export async function syncMessages(rows) {
|
|
|
190
190
|
export async function claimMessage(id, hostId) {
|
|
191
191
|
return apiFetch(`/api/messages/${id}/claim`, {
|
|
192
192
|
method: 'POST',
|
|
193
|
-
body: JSON.stringify(
|
|
193
|
+
body: JSON.stringify(withTiclawkVersion({ runtime_host_id: hostId })),
|
|
194
194
|
});
|
|
195
195
|
}
|
|
196
196
|
|
|
@@ -211,7 +211,7 @@ export async function completeMessage(id, hostId) {
|
|
|
211
211
|
export async function recoverClaimedMessages(hostId) {
|
|
212
212
|
return apiFetch('/api/messages/recover', {
|
|
213
213
|
method: 'POST',
|
|
214
|
-
body: JSON.stringify(
|
|
214
|
+
body: JSON.stringify(withTiclawkVersion({ runtime_host_id: hostId })),
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
|
|
@@ -300,15 +300,15 @@ export function createTiclawkAdapter(ctx) {
|
|
|
300
300
|
if (!state?.updateRequired) {
|
|
301
301
|
return {
|
|
302
302
|
updateRequired: false,
|
|
303
|
-
|
|
303
|
+
ticlawkVersion: api.getTiclawkVersion(),
|
|
304
304
|
managedInstall: isManagedInstall(),
|
|
305
305
|
};
|
|
306
306
|
}
|
|
307
307
|
return {
|
|
308
308
|
updateRequired: true,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
309
|
+
ticlawkVersion: api.getTiclawkVersion(),
|
|
310
|
+
currentTiclawkVersion: state.currentTiclawkVersion || api.getTiclawkVersion(),
|
|
311
|
+
requiredTiclawkVersion: state.requiredTiclawkVersion || null,
|
|
312
312
|
autoUpdateStatus: state.autoUpdateStatus || null,
|
|
313
313
|
autoUpdateError: state.autoUpdateError || null,
|
|
314
314
|
managedInstall: isManagedInstall(),
|
|
@@ -325,8 +325,8 @@ export function createTiclawkAdapter(ctx) {
|
|
|
325
325
|
|
|
326
326
|
function recordUpdateRequired(err, reason) {
|
|
327
327
|
const now = Date.now();
|
|
328
|
-
const currentVersion = err?.
|
|
329
|
-
const requiredVersion = err?.
|
|
328
|
+
const currentVersion = err?.currentTiclawkVersion || api.getTiclawkVersion();
|
|
329
|
+
const requiredVersion = err?.requiredTiclawkVersion || null;
|
|
330
330
|
const previousState = readUpdateState();
|
|
331
331
|
let autoUpdateStatus = previousState?.autoUpdateStatus || 'not_started';
|
|
332
332
|
let autoUpdateError = null;
|
|
@@ -334,7 +334,7 @@ export function createTiclawkAdapter(ctx) {
|
|
|
334
334
|
|
|
335
335
|
if (!requiredVersion) {
|
|
336
336
|
autoUpdateStatus = 'missing_required_version';
|
|
337
|
-
autoUpdateError = 'backend did not provide
|
|
337
|
+
autoUpdateError = 'backend did not provide required_ticlawk_version';
|
|
338
338
|
} else if (shouldAttemptAutoUpdate(previousState)) {
|
|
339
339
|
lastAutoUpdateAttemptAt = new Date().toISOString();
|
|
340
340
|
try {
|
|
@@ -347,8 +347,8 @@ export function createTiclawkAdapter(ctx) {
|
|
|
347
347
|
if (result.started) {
|
|
348
348
|
debugLog('ticlawk', 'update.auto-started', {
|
|
349
349
|
reason,
|
|
350
|
-
|
|
351
|
-
|
|
350
|
+
currentTiclawkVersion: currentVersion,
|
|
351
|
+
requiredTiclawkVersion: requiredVersion,
|
|
352
352
|
pid: result.pid || null,
|
|
353
353
|
logPath: result.logPath || null,
|
|
354
354
|
});
|
|
@@ -374,8 +374,8 @@ export function createTiclawkAdapter(ctx) {
|
|
|
374
374
|
lastUpdateRequiredLogAt = now;
|
|
375
375
|
debugError('ticlawk', 'update.required', {
|
|
376
376
|
reason,
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
currentTiclawkVersion: currentVersion,
|
|
378
|
+
requiredTiclawkVersion: requiredVersion,
|
|
379
379
|
autoUpdateStatus,
|
|
380
380
|
managedInstall: isManagedInstall(),
|
|
381
381
|
message: `Ticlawk requires ticlawk >= ${requiredVersion || 'unknown'}, current version is ${currentVersion || 'unknown'}. Please update ticlawk.`,
|
|
@@ -389,7 +389,7 @@ export function createTiclawkAdapter(ctx) {
|
|
|
389
389
|
clearUpdateRequiredState('ticlawk');
|
|
390
390
|
debugLog('ticlawk', 'update.cleared', {
|
|
391
391
|
reason,
|
|
392
|
-
|
|
392
|
+
currentTiclawkVersion: api.getTiclawkVersion(),
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
|
|
@@ -601,8 +601,8 @@ export function createTiclawkAdapter(ctx) {
|
|
|
601
601
|
debugLog('ticlawk', 'claim.paused-update-required', {
|
|
602
602
|
reason,
|
|
603
603
|
hostId,
|
|
604
|
-
|
|
605
|
-
|
|
604
|
+
currentTiclawkVersion: updateRequired.currentTiclawkVersion || api.getTiclawkVersion(),
|
|
605
|
+
requiredTiclawkVersion: updateRequired.requiredTiclawkVersion || null,
|
|
606
606
|
});
|
|
607
607
|
return { failed: true, claimed: 0, launched: 0, updateRequired: true };
|
|
608
608
|
}
|
|
@@ -884,7 +884,7 @@ export function createTiclawkAdapter(ctx) {
|
|
|
884
884
|
const clientSecret = makeClientSecret();
|
|
885
885
|
const created = await api.createPairingSession({
|
|
886
886
|
client: 'ticlawk',
|
|
887
|
-
client_version: api.
|
|
887
|
+
client_version: api.getTiclawkVersion(),
|
|
888
888
|
host_id: hostId,
|
|
889
889
|
host_label: hostLabel,
|
|
890
890
|
...(autoRuntime ? { runtime_options: runtimeOptions } : { runtime: resolved.runtime }),
|
package/src/core/config.mjs
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import dotenv from 'dotenv';
|
|
11
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
12
12
|
import { homedir } from 'node:os';
|
|
13
13
|
import { dirname, join } from 'node:path';
|
|
14
14
|
import { RUNTIME_DEFINITIONS, normalizeServiceType } from './runtime-registry.mjs';
|
|
@@ -18,9 +18,10 @@ const LEGACY_AGENT_FREEWAY_HOME = join(homedir(), '.agent-freeway');
|
|
|
18
18
|
|
|
19
19
|
function resolveTiclawkHome() {
|
|
20
20
|
if (process.env.TICLAWK_HOME) return process.env.TICLAWK_HOME;
|
|
21
|
-
if (
|
|
21
|
+
if (!existsSync(DEFAULT_TICLAWK_HOME) && existsSync(LEGACY_AGENT_FREEWAY_HOME)) {
|
|
22
|
+
renameSync(LEGACY_AGENT_FREEWAY_HOME, DEFAULT_TICLAWK_HOME);
|
|
23
|
+
}
|
|
22
24
|
if (existsSync(DEFAULT_TICLAWK_HOME)) return DEFAULT_TICLAWK_HOME;
|
|
23
|
-
if (existsSync(LEGACY_AGENT_FREEWAY_HOME)) return LEGACY_AGENT_FREEWAY_HOME;
|
|
24
25
|
return DEFAULT_TICLAWK_HOME;
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -49,9 +50,6 @@ export const SUPPORTED_ADAPTERS = ['ticlawk', 'telegram'];
|
|
|
49
50
|
export const ADAPTER_CONFIG_KEYS = {
|
|
50
51
|
'telegram.bot-token': 'TELEGRAM_BOT_TOKEN',
|
|
51
52
|
'ticlawk.connector-api-key': TICLAWK_CONNECTOR_API_KEY,
|
|
52
|
-
// Backward-compatible CLI alias. This intentionally maps to the connector
|
|
53
|
-
// key instead of the generic publisher-facing TICLAWK_API_KEY name.
|
|
54
|
-
'ticlawk.api-key': TICLAWK_CONNECTOR_API_KEY,
|
|
55
53
|
'ticlawk.api-url': 'TICLAWK_API_URL',
|
|
56
54
|
'ticlawk.connector-ws-url': TICLAWK_CONNECTOR_WS_URL,
|
|
57
55
|
};
|
|
@@ -136,8 +136,6 @@ WantedBy=default.target
|
|
|
136
136
|
`);
|
|
137
137
|
|
|
138
138
|
runRequired('systemd daemon-reload', 'systemctl', ['--user', 'daemon-reload']);
|
|
139
|
-
run('systemctl', ['--user', 'stop', 'agent-freeway']);
|
|
140
|
-
run('systemctl', ['--user', 'disable', 'agent-freeway']);
|
|
141
139
|
runRequired('systemd enable', 'systemctl', ['--user', 'enable', 'ticlawk']);
|
|
142
140
|
|
|
143
141
|
if (run('systemctl', ['--user', 'is-active', '--quiet', 'ticlawk']).status === 0) {
|
|
@@ -156,7 +154,6 @@ function installLaunchd() {
|
|
|
156
154
|
}
|
|
157
155
|
|
|
158
156
|
const plistDir = join(homedir(), 'Library', 'LaunchAgents');
|
|
159
|
-
const legacyLabels = ['agent-freeway', 'com.ticlawk.agent-freeway'];
|
|
160
157
|
const launchdLabel = 'ticlawk';
|
|
161
158
|
const plistFile = join(plistDir, `${launchdLabel}.plist`);
|
|
162
159
|
const uid = String(process.getuid?.() || '');
|
|
@@ -199,9 +196,6 @@ function installLaunchd() {
|
|
|
199
196
|
runRequired('launchd plist validation', 'plutil', ['-lint', plistFile]);
|
|
200
197
|
}
|
|
201
198
|
|
|
202
|
-
for (const legacyLabel of legacyLabels) {
|
|
203
|
-
run('launchctl', ['bootout', `${launchdDomain}/${legacyLabel}`]);
|
|
204
|
-
}
|
|
205
199
|
if (run('launchctl', ['print', launchdService]).status === 0) {
|
|
206
200
|
runRequired('launchd kickstart', 'launchctl', ['kickstart', '-k', launchdService]);
|
|
207
201
|
console.log(`launchd service restarted: ${launchdService}`);
|
package/src/core/uninstall.mjs
CHANGED
|
@@ -11,13 +11,12 @@ import { homedir } from 'node:os';
|
|
|
11
11
|
import { join } from 'node:path';
|
|
12
12
|
import { AF_HOME } from './config.mjs';
|
|
13
13
|
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
return [join(dataHome, 'ticlawk'), join(dataHome, 'agent-freeway')];
|
|
14
|
+
function getInstallRoot() {
|
|
15
|
+
return join(process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share'), 'ticlawk');
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
function
|
|
20
|
-
return
|
|
18
|
+
function getWrapperPath() {
|
|
19
|
+
return join(homedir(), '.local', 'bin', 'ticlawk');
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
function commandExists(command) {
|
|
@@ -67,22 +66,17 @@ function removePath(path, label, { recursive = false } = {}) {
|
|
|
67
66
|
|
|
68
67
|
function uninstallSystemd() {
|
|
69
68
|
if (process.platform !== 'linux' || !commandExists('systemctl')) return;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
removePath(join(homedir(), '.config', 'systemd', 'user', `${service}.service`), 'systemd service');
|
|
74
|
-
}
|
|
69
|
+
runBestEffort('systemd stop', 'systemctl', ['--user', 'stop', 'ticlawk']);
|
|
70
|
+
runBestEffort('systemd disable', 'systemctl', ['--user', 'disable', 'ticlawk']);
|
|
71
|
+
removePath(join(homedir(), '.config', 'systemd', 'user', 'ticlawk.service'), 'systemd service');
|
|
75
72
|
runBestEffort('systemd daemon-reload', 'systemctl', ['--user', 'daemon-reload'], { warn: true });
|
|
76
73
|
}
|
|
77
74
|
|
|
78
75
|
function uninstallLaunchd() {
|
|
79
76
|
if (process.platform !== 'darwin' || !commandExists('launchctl')) return;
|
|
80
77
|
const uid = String(process.getuid?.() || '');
|
|
81
|
-
|
|
82
|
-
runBestEffort(`launchd unload ${label}`, 'launchctl', ['bootout', `gui/${uid}/${label}`]);
|
|
83
|
-
}
|
|
78
|
+
runBestEffort('launchd unload ticlawk', 'launchctl', ['bootout', `gui/${uid}/ticlawk`]);
|
|
84
79
|
removePath(join(homedir(), 'Library', 'LaunchAgents', 'ticlawk.plist'), 'launchd plist');
|
|
85
|
-
removePath(join(homedir(), 'Library', 'LaunchAgents', 'agent-freeway.plist'), 'launchd plist');
|
|
86
80
|
}
|
|
87
81
|
|
|
88
82
|
export function getUninstallHelp() {
|
|
@@ -92,11 +86,11 @@ Remove the ticlawk service and legacy install files while preserving local data.
|
|
|
92
86
|
|
|
93
87
|
Removes:
|
|
94
88
|
- user service: systemd on Linux, launchd on macOS
|
|
95
|
-
- CLI
|
|
96
|
-
- legacy managed
|
|
89
|
+
- CLI wrapper: ~/.local/bin/ticlawk
|
|
90
|
+
- legacy managed install: ~/.local/share/ticlawk
|
|
97
91
|
|
|
98
92
|
Preserves:
|
|
99
|
-
- ~/.ticlawk
|
|
93
|
+
- ~/.ticlawk
|
|
100
94
|
|
|
101
95
|
To remove the npm package itself:
|
|
102
96
|
npm uninstall -g ticlawk
|
|
@@ -108,13 +102,13 @@ Usage:
|
|
|
108
102
|
}
|
|
109
103
|
|
|
110
104
|
export async function runSelfUninstall(skipPrompt) {
|
|
111
|
-
const
|
|
112
|
-
const
|
|
105
|
+
const installRoot = getInstallRoot();
|
|
106
|
+
const wrapperPath = getWrapperPath();
|
|
113
107
|
|
|
114
108
|
console.log('ticlawk uninstall');
|
|
115
109
|
console.log('will remove the user service');
|
|
116
|
-
console.log(`will remove legacy install files under: ${
|
|
117
|
-
console.log(`will remove CLI
|
|
110
|
+
console.log(`will remove legacy install files under: ${installRoot}`);
|
|
111
|
+
console.log(`will remove CLI wrapper: ${wrapperPath}`);
|
|
118
112
|
console.log(`will preserve data directory: ${AF_HOME}`);
|
|
119
113
|
|
|
120
114
|
if (!skipPrompt) {
|
|
@@ -131,12 +125,8 @@ export async function runSelfUninstall(skipPrompt) {
|
|
|
131
125
|
|
|
132
126
|
uninstallSystemd();
|
|
133
127
|
uninstallLaunchd();
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
for (const installRoot of installRoots) {
|
|
138
|
-
removePath(installRoot, 'package install', { recursive: true });
|
|
139
|
-
}
|
|
128
|
+
removePath(wrapperPath, 'CLI wrapper');
|
|
129
|
+
removePath(installRoot, 'package install', { recursive: true });
|
|
140
130
|
console.log(`preserved data directory: ${AF_HOME}`);
|
|
141
131
|
console.log('uninstall complete');
|
|
142
132
|
}
|
|
@@ -39,8 +39,8 @@ export function setUpdateRequiredState({ adapter, currentVersion, requiredVersio
|
|
|
39
39
|
const updates = {
|
|
40
40
|
adapter,
|
|
41
41
|
updateRequired: true,
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
currentTiclawkVersion: currentVersion || null,
|
|
43
|
+
requiredTiclawkVersion: requiredVersion || null,
|
|
44
44
|
};
|
|
45
45
|
if (autoUpdateStatus) updates.autoUpdateStatus = autoUpdateStatus;
|
|
46
46
|
if (autoUpdateError) updates.autoUpdateError = autoUpdateError;
|
package/src/core/update.mjs
CHANGED
|
@@ -30,19 +30,15 @@ function commandExists(command) {
|
|
|
30
30
|
|
|
31
31
|
export function isManagedInstall() {
|
|
32
32
|
if (process.platform === 'linux' && commandExists('systemctl')) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return enabled.status === 0 || active.status === 0;
|
|
37
|
-
});
|
|
33
|
+
const enabled = spawnSync('systemctl', ['--user', 'is-enabled', '--quiet', 'ticlawk'], { stdio: 'ignore' });
|
|
34
|
+
const active = spawnSync('systemctl', ['--user', 'is-active', '--quiet', 'ticlawk'], { stdio: 'ignore' });
|
|
35
|
+
return enabled.status === 0 || active.status === 0;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
if (process.platform === 'darwin' && commandExists('launchctl')) {
|
|
41
39
|
const uid = String(process.getuid?.() || '');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return spawnSync('launchctl', ['print', service], { stdio: 'ignore' }).status === 0;
|
|
45
|
-
});
|
|
40
|
+
const service = `gui/${uid}/ticlawk`;
|
|
41
|
+
return spawnSync('launchctl', ['print', service], { stdio: 'ignore' }).status === 0;
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
return false;
|
|
@@ -79,10 +75,6 @@ export function startDetachedSelfUpdate({ requiredVersion = '', currentVersion =
|
|
|
79
75
|
TICLAWK_REQUIRED_VERSION: requiredVersion,
|
|
80
76
|
TICLAWK_CURRENT_VERSION: currentVersion,
|
|
81
77
|
...(installerVersion ? { TICLAWK_VERSION: installerVersion } : {}),
|
|
82
|
-
AGENT_FREEWAY_UPDATE_REASON: reason,
|
|
83
|
-
AGENT_FREEWAY_REQUIRED_VERSION: requiredVersion,
|
|
84
|
-
AGENT_FREEWAY_CURRENT_VERSION: currentVersion,
|
|
85
|
-
...(installerVersion ? { AGENT_FREEWAY_VERSION: installerVersion } : {}),
|
|
86
78
|
},
|
|
87
79
|
});
|
|
88
80
|
child.unref();
|
|
@@ -135,8 +127,6 @@ export async function runSelfUpdate(skipPrompt) {
|
|
|
135
127
|
const currentVersion = readPkgVersion();
|
|
136
128
|
const targetVersion = process.env.TICLAWK_VERSION
|
|
137
129
|
|| process.env.TICLAWK_REQUIRED_VERSION
|
|
138
|
-
|| process.env.AGENT_FREEWAY_VERSION
|
|
139
|
-
|| process.env.AGENT_FREEWAY_REQUIRED_VERSION
|
|
140
130
|
|| 'latest';
|
|
141
131
|
const packageSpec = `${PACKAGE_NAME}@${targetVersion}`;
|
|
142
132
|
console.log(`current version: ${currentVersion || '(unknown)'}`);
|
package/agent-freeway.mjs
DELETED
package/bin/agent-freeway.mjs
DELETED