sidekick-shared 0.20.0 → 0.21.0
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 +12 -0
- package/dist/accountManager.d.ts +52 -0
- package/dist/accountManager.js +344 -0
- package/dist/accounts.d.ts +3 -0
- package/dist/accounts.js +180 -40
- package/dist/autoSwitch.d.ts +70 -0
- package/dist/autoSwitch.js +160 -0
- package/dist/claudeProfiles.d.ts +12 -0
- package/dist/claudeProfiles.js +96 -0
- package/dist/codexProfiles.d.ts +6 -2
- package/dist/codexProfiles.js +6 -1
- package/dist/credentialIO.d.ts +3 -2
- package/dist/credentialIO.js +11 -9
- package/dist/ensureDefaultAccounts.js +6 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +41 -3
- package/dist/schemas/accountManager.d.ts +104 -0
- package/dist/schemas/accountManager.js +84 -0
- package/dist/schemas/assistantTurn.d.ts +5 -5
- package/dist/schemas/index.d.ts +4 -0
- package/dist/schemas/index.js +9 -1
- package/dist/schemas/quota.d.ts +20 -20
- package/dist/schemas/quotaHistory.d.ts +1 -1
- package/dist/terminalSync.d.ts +7 -0
- package/dist/terminalSync.js +202 -0
- package/package.json +1 -1
package/dist/schemas/quota.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ export declare const quotaWindowSchema: z.ZodObject<{
|
|
|
15
15
|
}, z.core.$strip>;
|
|
16
16
|
export declare const quotaFailureKindSchema: z.ZodEnum<{
|
|
17
17
|
unknown: "unknown";
|
|
18
|
-
rate_limit: "rate_limit";
|
|
19
18
|
auth: "auth";
|
|
20
19
|
network: "network";
|
|
20
|
+
rate_limit: "rate_limit";
|
|
21
21
|
server: "server";
|
|
22
22
|
}>;
|
|
23
23
|
export declare const quotaProviderIdSchema: z.ZodEnum<{
|
|
@@ -25,8 +25,8 @@ export declare const quotaProviderIdSchema: z.ZodEnum<{
|
|
|
25
25
|
codex: "codex";
|
|
26
26
|
}>;
|
|
27
27
|
export declare const quotaSourceSchema: z.ZodEnum<{
|
|
28
|
-
session: "session";
|
|
29
28
|
api: "api";
|
|
29
|
+
session: "session";
|
|
30
30
|
cache: "cache";
|
|
31
31
|
}>;
|
|
32
32
|
export declare const quotaStateSchema: z.ZodObject<{
|
|
@@ -42,9 +42,9 @@ export declare const quotaStateSchema: z.ZodObject<{
|
|
|
42
42
|
error: z.ZodOptional<z.ZodString>;
|
|
43
43
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
44
44
|
unknown: "unknown";
|
|
45
|
-
rate_limit: "rate_limit";
|
|
46
45
|
auth: "auth";
|
|
47
46
|
network: "network";
|
|
47
|
+
rate_limit: "rate_limit";
|
|
48
48
|
server: "server";
|
|
49
49
|
}>>;
|
|
50
50
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -56,8 +56,8 @@ export declare const quotaStateSchema: z.ZodObject<{
|
|
|
56
56
|
codex: "codex";
|
|
57
57
|
}>>;
|
|
58
58
|
source: z.ZodOptional<z.ZodEnum<{
|
|
59
|
-
session: "session";
|
|
60
59
|
api: "api";
|
|
60
|
+
session: "session";
|
|
61
61
|
cache: "cache";
|
|
62
62
|
}>>;
|
|
63
63
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -94,8 +94,8 @@ export declare const peakHoursStateSchema: z.ZodObject<{
|
|
|
94
94
|
export declare const quotaFailureDescriptorSchema: z.ZodObject<{
|
|
95
95
|
severity: z.ZodEnum<{
|
|
96
96
|
error: "error";
|
|
97
|
-
info: "info";
|
|
98
97
|
warning: "warning";
|
|
98
|
+
info: "info";
|
|
99
99
|
}>;
|
|
100
100
|
title: z.ZodString;
|
|
101
101
|
message: z.ZodString;
|
|
@@ -120,9 +120,9 @@ export declare const providerQuotaStateSchema: z.ZodObject<{
|
|
|
120
120
|
error: z.ZodOptional<z.ZodString>;
|
|
121
121
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
122
122
|
unknown: "unknown";
|
|
123
|
-
rate_limit: "rate_limit";
|
|
124
123
|
auth: "auth";
|
|
125
124
|
network: "network";
|
|
125
|
+
rate_limit: "rate_limit";
|
|
126
126
|
server: "server";
|
|
127
127
|
}>>;
|
|
128
128
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -134,8 +134,8 @@ export declare const providerQuotaStateSchema: z.ZodObject<{
|
|
|
134
134
|
codex: "codex";
|
|
135
135
|
}>>;
|
|
136
136
|
source: z.ZodOptional<z.ZodEnum<{
|
|
137
|
-
session: "session";
|
|
138
137
|
api: "api";
|
|
138
|
+
session: "session";
|
|
139
139
|
cache: "cache";
|
|
140
140
|
}>>;
|
|
141
141
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -173,8 +173,8 @@ export declare const providerQuotaStateSchema: z.ZodObject<{
|
|
|
173
173
|
failure: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
174
174
|
severity: z.ZodEnum<{
|
|
175
175
|
error: "error";
|
|
176
|
-
info: "info";
|
|
177
176
|
warning: "warning";
|
|
177
|
+
info: "info";
|
|
178
178
|
}>;
|
|
179
179
|
title: z.ZodString;
|
|
180
180
|
message: z.ZodString;
|
|
@@ -200,9 +200,9 @@ export declare const claudeProviderQuotaStateSchema: z.ZodObject<{
|
|
|
200
200
|
error: z.ZodOptional<z.ZodString>;
|
|
201
201
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
202
202
|
unknown: "unknown";
|
|
203
|
-
rate_limit: "rate_limit";
|
|
204
203
|
auth: "auth";
|
|
205
204
|
network: "network";
|
|
205
|
+
rate_limit: "rate_limit";
|
|
206
206
|
server: "server";
|
|
207
207
|
}>>;
|
|
208
208
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -214,8 +214,8 @@ export declare const claudeProviderQuotaStateSchema: z.ZodObject<{
|
|
|
214
214
|
codex: "codex";
|
|
215
215
|
}>>;
|
|
216
216
|
source: z.ZodOptional<z.ZodEnum<{
|
|
217
|
-
session: "session";
|
|
218
217
|
api: "api";
|
|
218
|
+
session: "session";
|
|
219
219
|
cache: "cache";
|
|
220
220
|
}>>;
|
|
221
221
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -253,8 +253,8 @@ export declare const claudeProviderQuotaStateSchema: z.ZodObject<{
|
|
|
253
253
|
failure: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
254
254
|
severity: z.ZodEnum<{
|
|
255
255
|
error: "error";
|
|
256
|
-
info: "info";
|
|
257
256
|
warning: "warning";
|
|
257
|
+
info: "info";
|
|
258
258
|
}>;
|
|
259
259
|
title: z.ZodString;
|
|
260
260
|
message: z.ZodString;
|
|
@@ -277,9 +277,9 @@ export declare const codexProviderQuotaStateSchema: z.ZodObject<{
|
|
|
277
277
|
error: z.ZodOptional<z.ZodString>;
|
|
278
278
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
279
279
|
unknown: "unknown";
|
|
280
|
-
rate_limit: "rate_limit";
|
|
281
280
|
auth: "auth";
|
|
282
281
|
network: "network";
|
|
282
|
+
rate_limit: "rate_limit";
|
|
283
283
|
server: "server";
|
|
284
284
|
}>>;
|
|
285
285
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -291,8 +291,8 @@ export declare const codexProviderQuotaStateSchema: z.ZodObject<{
|
|
|
291
291
|
codex: "codex";
|
|
292
292
|
}>>;
|
|
293
293
|
source: z.ZodOptional<z.ZodEnum<{
|
|
294
|
-
session: "session";
|
|
295
294
|
api: "api";
|
|
295
|
+
session: "session";
|
|
296
296
|
cache: "cache";
|
|
297
297
|
}>>;
|
|
298
298
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -330,8 +330,8 @@ export declare const codexProviderQuotaStateSchema: z.ZodObject<{
|
|
|
330
330
|
failure: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
331
331
|
severity: z.ZodEnum<{
|
|
332
332
|
error: "error";
|
|
333
|
-
info: "info";
|
|
334
333
|
warning: "warning";
|
|
334
|
+
info: "info";
|
|
335
335
|
}>;
|
|
336
336
|
title: z.ZodString;
|
|
337
337
|
message: z.ZodString;
|
|
@@ -355,9 +355,9 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
355
355
|
error: z.ZodOptional<z.ZodString>;
|
|
356
356
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
357
357
|
unknown: "unknown";
|
|
358
|
-
rate_limit: "rate_limit";
|
|
359
358
|
auth: "auth";
|
|
360
359
|
network: "network";
|
|
360
|
+
rate_limit: "rate_limit";
|
|
361
361
|
server: "server";
|
|
362
362
|
}>>;
|
|
363
363
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -369,8 +369,8 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
369
369
|
codex: "codex";
|
|
370
370
|
}>>;
|
|
371
371
|
source: z.ZodOptional<z.ZodEnum<{
|
|
372
|
-
session: "session";
|
|
373
372
|
api: "api";
|
|
373
|
+
session: "session";
|
|
374
374
|
cache: "cache";
|
|
375
375
|
}>>;
|
|
376
376
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -408,8 +408,8 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
408
408
|
failure: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
409
409
|
severity: z.ZodEnum<{
|
|
410
410
|
error: "error";
|
|
411
|
-
info: "info";
|
|
412
411
|
warning: "warning";
|
|
412
|
+
info: "info";
|
|
413
413
|
}>;
|
|
414
414
|
title: z.ZodString;
|
|
415
415
|
message: z.ZodString;
|
|
@@ -432,9 +432,9 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
432
432
|
error: z.ZodOptional<z.ZodString>;
|
|
433
433
|
failureKind: z.ZodOptional<z.ZodEnum<{
|
|
434
434
|
unknown: "unknown";
|
|
435
|
-
rate_limit: "rate_limit";
|
|
436
435
|
auth: "auth";
|
|
437
436
|
network: "network";
|
|
437
|
+
rate_limit: "rate_limit";
|
|
438
438
|
server: "server";
|
|
439
439
|
}>>;
|
|
440
440
|
httpStatus: z.ZodOptional<z.ZodNumber>;
|
|
@@ -446,8 +446,8 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
446
446
|
codex: "codex";
|
|
447
447
|
}>>;
|
|
448
448
|
source: z.ZodOptional<z.ZodEnum<{
|
|
449
|
-
session: "session";
|
|
450
449
|
api: "api";
|
|
450
|
+
session: "session";
|
|
451
451
|
cache: "cache";
|
|
452
452
|
}>>;
|
|
453
453
|
capturedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -485,8 +485,8 @@ export declare const providerQuotaMapSchema: z.ZodObject<{
|
|
|
485
485
|
failure: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
486
486
|
severity: z.ZodEnum<{
|
|
487
487
|
error: "error";
|
|
488
|
-
info: "info";
|
|
489
488
|
warning: "warning";
|
|
489
|
+
info: "info";
|
|
490
490
|
}>;
|
|
491
491
|
title: z.ZodString;
|
|
492
492
|
message: z.ZodString;
|
|
@@ -32,8 +32,8 @@ export declare const quotaHistorySampleSchema: z.ZodObject<{
|
|
|
32
32
|
available: z.ZodBoolean;
|
|
33
33
|
error: z.ZodOptional<z.ZodString>;
|
|
34
34
|
source: z.ZodOptional<z.ZodEnum<{
|
|
35
|
-
session: "session";
|
|
36
35
|
api: "api";
|
|
36
|
+
session: "session";
|
|
37
37
|
cache: "cache";
|
|
38
38
|
}>>;
|
|
39
39
|
stale: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AccountProviderId } from './accountRegistry';
|
|
2
|
+
export declare function setTerminalActiveProfile(provider: AccountProviderId, home: string | null): void;
|
|
3
|
+
export declare function installShellHook(): void;
|
|
4
|
+
export declare function uninstallShellHook(): void;
|
|
5
|
+
export declare function isShellHookInstalled(): boolean;
|
|
6
|
+
export declare function writeLauncher(name: string, provider: AccountProviderId, profileHome: string): void;
|
|
7
|
+
export declare function removeLauncher(name: string): void;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.setTerminalActiveProfile = setTerminalActiveProfile;
|
|
37
|
+
exports.installShellHook = installShellHook;
|
|
38
|
+
exports.uninstallShellHook = uninstallShellHook;
|
|
39
|
+
exports.isShellHookInstalled = isShellHookInstalled;
|
|
40
|
+
exports.writeLauncher = writeLauncher;
|
|
41
|
+
exports.removeLauncher = removeLauncher;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const os = __importStar(require("os"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const accountRegistry_1 = require("./accountRegistry");
|
|
46
|
+
const HOOK_START = '# >>> sidekick >>>';
|
|
47
|
+
const HOOK_END = '# <<< sidekick <<<';
|
|
48
|
+
const LAUNCHER_MARKER = '# sidekick-launcher v1';
|
|
49
|
+
const LAUNCHER_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
50
|
+
function providerPointerName(provider) {
|
|
51
|
+
return provider === 'claude-code' ? 'claude' : 'codex';
|
|
52
|
+
}
|
|
53
|
+
function providerEnvVar(provider) {
|
|
54
|
+
return provider === 'claude-code' ? 'CLAUDE_CONFIG_DIR' : 'CODEX_HOME';
|
|
55
|
+
}
|
|
56
|
+
function providerBinary(provider) {
|
|
57
|
+
return provider === 'claude-code' ? 'claude' : 'codex';
|
|
58
|
+
}
|
|
59
|
+
function getActiveProfilesDir() {
|
|
60
|
+
return path.join((0, accountRegistry_1.getAccountsDir)(), 'active');
|
|
61
|
+
}
|
|
62
|
+
function getActiveProfilePath(provider) {
|
|
63
|
+
return path.join(getActiveProfilesDir(), `${providerPointerName(provider)}.profile`);
|
|
64
|
+
}
|
|
65
|
+
function atomicWriteFile(filePath, content, mode = 0o600) {
|
|
66
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
67
|
+
const tmp = `${filePath}.tmp`;
|
|
68
|
+
try {
|
|
69
|
+
fs.writeFileSync(tmp, content, { encoding: 'utf8', mode });
|
|
70
|
+
fs.renameSync(tmp, filePath);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
try {
|
|
74
|
+
fs.rmSync(tmp, { force: true });
|
|
75
|
+
}
|
|
76
|
+
catch { /* nothing to clean up */ }
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function setTerminalActiveProfile(provider, home) {
|
|
81
|
+
const pointerPath = getActiveProfilePath(provider);
|
|
82
|
+
if (home === null) {
|
|
83
|
+
fs.rmSync(pointerPath, { force: true });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
atomicWriteFile(pointerPath, `${home}\n`);
|
|
87
|
+
}
|
|
88
|
+
function shellQuote(value) {
|
|
89
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
90
|
+
}
|
|
91
|
+
function buildShellHookBlock() {
|
|
92
|
+
const claudePointer = getActiveProfilePath('claude-code');
|
|
93
|
+
const codexPointer = getActiveProfilePath('codex');
|
|
94
|
+
return [
|
|
95
|
+
HOOK_START,
|
|
96
|
+
'sidekick_sync() {',
|
|
97
|
+
` if [ -r ${shellQuote(claudePointer)} ]; then export CLAUDE_CONFIG_DIR="$(cat ${shellQuote(claudePointer)})"; else unset CLAUDE_CONFIG_DIR; fi`,
|
|
98
|
+
` if [ -r ${shellQuote(codexPointer)} ]; then export CODEX_HOME="$(cat ${shellQuote(codexPointer)})"; else unset CODEX_HOME; fi`,
|
|
99
|
+
'}',
|
|
100
|
+
'sidekick_sync >/dev/null 2>&1',
|
|
101
|
+
HOOK_END,
|
|
102
|
+
'',
|
|
103
|
+
].join('\n');
|
|
104
|
+
}
|
|
105
|
+
function getShellRcPaths() {
|
|
106
|
+
const zshrc = path.join(os.homedir(), '.zshrc');
|
|
107
|
+
const bashrc = path.join(os.homedir(), '.bashrc');
|
|
108
|
+
const paths = [zshrc];
|
|
109
|
+
if (fs.existsSync(bashrc))
|
|
110
|
+
paths.push(bashrc);
|
|
111
|
+
return paths;
|
|
112
|
+
}
|
|
113
|
+
function stripShellHook(content) {
|
|
114
|
+
const pattern = new RegExp(`${HOOK_START}[\\s\\S]*?${HOOK_END}\\n?`, 'g');
|
|
115
|
+
return content.replace(pattern, '').replace(/\n{3,}/g, '\n\n');
|
|
116
|
+
}
|
|
117
|
+
function installHookInFile(filePath) {
|
|
118
|
+
const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';
|
|
119
|
+
const cleaned = stripShellHook(existing).replace(/\s*$/, '');
|
|
120
|
+
const next = cleaned ? `${cleaned}\n\n${buildShellHookBlock()}` : buildShellHookBlock();
|
|
121
|
+
atomicWriteFile(filePath, next, 0o600);
|
|
122
|
+
}
|
|
123
|
+
function installShellHook() {
|
|
124
|
+
for (const rcPath of getShellRcPaths()) {
|
|
125
|
+
installHookInFile(rcPath);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function uninstallHookInFile(filePath) {
|
|
129
|
+
if (!fs.existsSync(filePath))
|
|
130
|
+
return;
|
|
131
|
+
atomicWriteFile(filePath, stripShellHook(fs.readFileSync(filePath, 'utf8')), 0o600);
|
|
132
|
+
}
|
|
133
|
+
function uninstallShellHook() {
|
|
134
|
+
for (const rcPath of getShellRcPaths()) {
|
|
135
|
+
uninstallHookInFile(rcPath);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function isShellHookInstalled() {
|
|
139
|
+
return getShellRcPaths().some(rcPath => {
|
|
140
|
+
try {
|
|
141
|
+
const content = fs.readFileSync(rcPath, 'utf8');
|
|
142
|
+
return content.includes(HOOK_START) && content.includes(HOOK_END);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function getLauncherDir() {
|
|
150
|
+
return path.join(os.homedir(), '.local', 'bin');
|
|
151
|
+
}
|
|
152
|
+
function getLauncherPath(name) {
|
|
153
|
+
return path.join(getLauncherDir(), name);
|
|
154
|
+
}
|
|
155
|
+
function assertValidLauncherName(name) {
|
|
156
|
+
if (!LAUNCHER_NAME_PATTERN.test(name)) {
|
|
157
|
+
throw new Error(`Invalid launcher name "${name}". Use letters, numbers, underscores, and hyphens only.`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function isSidekickLauncher(filePath) {
|
|
161
|
+
try {
|
|
162
|
+
return fs.readFileSync(filePath, 'utf8').includes(LAUNCHER_MARKER);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function assertNoLauncherCollision(name, targetPath) {
|
|
169
|
+
if (fs.existsSync(targetPath) && !isSidekickLauncher(targetPath)) {
|
|
170
|
+
throw new Error(`Launcher "${name}" already exists and is not managed by sidekick.`);
|
|
171
|
+
}
|
|
172
|
+
for (const dir of (process.env.PATH ?? '').split(path.delimiter).filter(Boolean)) {
|
|
173
|
+
const candidate = path.join(dir, name);
|
|
174
|
+
if (path.resolve(candidate) === path.resolve(targetPath))
|
|
175
|
+
continue;
|
|
176
|
+
if (fs.existsSync(candidate)) {
|
|
177
|
+
throw new Error(`Launcher "${name}" collides with an existing command on PATH.`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function writeLauncher(name, provider, profileHome) {
|
|
182
|
+
assertValidLauncherName(name);
|
|
183
|
+
const launcherPath = getLauncherPath(name);
|
|
184
|
+
assertNoLauncherCollision(name, launcherPath);
|
|
185
|
+
const envVar = providerEnvVar(provider);
|
|
186
|
+
const binary = providerBinary(provider);
|
|
187
|
+
const script = [
|
|
188
|
+
'#!/bin/sh',
|
|
189
|
+
LAUNCHER_MARKER,
|
|
190
|
+
`export ${envVar}=${JSON.stringify(profileHome)}`,
|
|
191
|
+
`exec ${binary} "$@"`,
|
|
192
|
+
'',
|
|
193
|
+
].join('\n');
|
|
194
|
+
atomicWriteFile(launcherPath, script, 0o755);
|
|
195
|
+
}
|
|
196
|
+
function removeLauncher(name) {
|
|
197
|
+
assertValidLauncherName(name);
|
|
198
|
+
const launcherPath = getLauncherPath(name);
|
|
199
|
+
if (!isSidekickLauncher(launcherPath))
|
|
200
|
+
return;
|
|
201
|
+
fs.rmSync(launcherPath, { force: true });
|
|
202
|
+
}
|
package/package.json
CHANGED