@apilift/cli 1.4.28 → 1.4.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/apilift-capture-server.js +68 -25
- package/dist/apilift-collector.js +18 -6
- package/dist/apilift-native-host.js +7 -6
- package/dist/apilift-register-native-host.js +108 -27
- package/dist/apilift-session-audit.js +18 -6
- package/dist/apilift.js +995 -738
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.codex-plugin/plugin.json +1 -1
- package/package.json +3 -2
package/dist/apilift.js
CHANGED
|
@@ -30308,12 +30308,12 @@ import { dirname, join as join3 } from "node:path";
|
|
|
30308
30308
|
function pathFor(root, appSlug, kind, name) {
|
|
30309
30309
|
if (!slugPattern.test(appSlug)) throw new Error("App slug is invalid");
|
|
30310
30310
|
if (kind === "action" ? !actionPattern.test(name) : kind !== "app" && !resourcePattern.test(name)) throw new Error("Resource name is invalid");
|
|
30311
|
-
return kind === "app" ? join3(root, "drafts", appSlug, "app.jsonc") : join3(root, "drafts", appSlug, paths[kind], `${name}.jsonc`);
|
|
30311
|
+
return kind === "app" ? join3(root, "drafts", diskName(appSlug), "app.jsonc") : join3(root, "drafts", diskName(appSlug), paths[kind], `${diskName(name)}.jsonc`);
|
|
30312
30312
|
}
|
|
30313
30313
|
function record2(row) {
|
|
30314
30314
|
return { id: String(row.id), appSlug: String(row.app_slug), appId: row.app_id === null ? null : String(row.app_id), kind: String(row.kind), name: String(row.name), ownerSessionId: row.owner_session_id === null ? null : String(row.owner_session_id), filePath: String(row.file_path), intent: row.intent === "remove" ? "remove" : "edit", baseVersion: row.base_version === null ? null : Number(row.base_version) };
|
|
30315
30315
|
}
|
|
30316
|
-
var DraftConflict, paths, slugPattern, resourcePattern, actionPattern, DraftStore;
|
|
30316
|
+
var DraftConflict, paths, slugPattern, resourcePattern, actionPattern, diskName, DraftStore;
|
|
30317
30317
|
var init_drafts = __esm({
|
|
30318
30318
|
"src/discovery/drafts.ts"() {
|
|
30319
30319
|
"use strict";
|
|
@@ -30329,6 +30329,7 @@ var init_drafts = __esm({
|
|
|
30329
30329
|
slugPattern = /^[a-z][a-z0-9-]{0,79}$/u;
|
|
30330
30330
|
resourcePattern = /^[a-z][a-z0-9_-]{0,79}$/u;
|
|
30331
30331
|
actionPattern = /^[a-z][a-z0-9_-]{0,79}\.[a-z][a-z0-9_-]{0,79}$/u;
|
|
30332
|
+
diskName = (name) => /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/iu.test(name) ? `~${name}` : name;
|
|
30332
30333
|
DraftStore = class {
|
|
30333
30334
|
constructor(state, root) {
|
|
30334
30335
|
this.state = state;
|
|
@@ -31114,8 +31115,24 @@ var require_dist = __commonJS({
|
|
|
31114
31115
|
}
|
|
31115
31116
|
});
|
|
31116
31117
|
|
|
31117
|
-
// src/
|
|
31118
|
+
// src/process.ts
|
|
31118
31119
|
import { spawn } from "node:child_process";
|
|
31120
|
+
function backgroundOptions(env, platform4 = process.platform) {
|
|
31121
|
+
return { detached: platform4 !== "win32", windowsHide: true, stdio: "ignore", env };
|
|
31122
|
+
}
|
|
31123
|
+
function startBackground(script, env, onError) {
|
|
31124
|
+
const child = spawn(process.execPath, [script], backgroundOptions(env));
|
|
31125
|
+
child.once("error", onError);
|
|
31126
|
+
child.unref();
|
|
31127
|
+
return child;
|
|
31128
|
+
}
|
|
31129
|
+
var init_process = __esm({
|
|
31130
|
+
"src/process.ts"() {
|
|
31131
|
+
"use strict";
|
|
31132
|
+
}
|
|
31133
|
+
});
|
|
31134
|
+
|
|
31135
|
+
// src/capture-server/client.ts
|
|
31119
31136
|
import { createHash as createHash2 } from "node:crypto";
|
|
31120
31137
|
import { chmodSync as chmodSync4, existsSync as existsSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync4, rmSync as rmSync2 } from "node:fs";
|
|
31121
31138
|
import { dirname as dirname2, join as join4 } from "node:path";
|
|
@@ -31133,6 +31150,9 @@ function compatibleBroker(client, health, requestedVersion) {
|
|
|
31133
31150
|
if (health.protocol === "apilift.capture/v1" || health.version === requestedVersion) return true;
|
|
31134
31151
|
return false;
|
|
31135
31152
|
}
|
|
31153
|
+
function reusableBroker(client, health, requestedVersion) {
|
|
31154
|
+
return compatibleBroker(client, health, requestedVersion) && (health.version === requestedVersion || health.active);
|
|
31155
|
+
}
|
|
31136
31156
|
function receiptAt(root) {
|
|
31137
31157
|
try {
|
|
31138
31158
|
const raw = JSON.parse(readFileSync4(join4(root, "server.json"), "utf8"));
|
|
@@ -31180,7 +31200,7 @@ async function ensureCaptureServerUnderUpdateLock(options2) {
|
|
|
31180
31200
|
if (current) {
|
|
31181
31201
|
const client = new CaptureServerClient(current);
|
|
31182
31202
|
try {
|
|
31183
|
-
if (
|
|
31203
|
+
if (reusableBroker(client, await client.health(), options2.version)) return client;
|
|
31184
31204
|
} catch {
|
|
31185
31205
|
}
|
|
31186
31206
|
}
|
|
@@ -31197,7 +31217,7 @@ async function ensureCaptureServerUnderUpdateLock(options2) {
|
|
|
31197
31217
|
const existing = new CaptureServerClient(previous);
|
|
31198
31218
|
try {
|
|
31199
31219
|
const health = await existing.health();
|
|
31200
|
-
if (
|
|
31220
|
+
if (reusableBroker(existing, health, options2.version)) return existing;
|
|
31201
31221
|
if (health.active) throw Object.assign(new Error("Capture server cannot be replaced while browser work is active"), { code: "capture-server-busy" });
|
|
31202
31222
|
await existing.retire();
|
|
31203
31223
|
} catch (error62) {
|
|
@@ -31209,10 +31229,13 @@ async function ensureCaptureServerUnderUpdateLock(options2) {
|
|
|
31209
31229
|
}
|
|
31210
31230
|
}
|
|
31211
31231
|
if (!existsSync2(options2.script)) throw new Error(`Capture server entry point is missing: ${options2.script}`);
|
|
31212
|
-
|
|
31213
|
-
child.
|
|
31232
|
+
let startupError;
|
|
31233
|
+
const child = startBackground(options2.script, { ...process.env, ...options2.env, APILIFT_HOME: root }, (error62) => {
|
|
31234
|
+
startupError = error62;
|
|
31235
|
+
});
|
|
31214
31236
|
const deadline = Date.now() + (options2.timeoutMs ?? 1e4);
|
|
31215
31237
|
while (Date.now() < deadline) {
|
|
31238
|
+
if (startupError || child.exitCode !== null) throw Object.assign(new Error("The local browser process could not start. Run apilift setup continue to repair the installation."), { code: "capture-server-unavailable" });
|
|
31216
31239
|
const current2 = receiptAt(root);
|
|
31217
31240
|
if (current2 && child.pid && current2.pid === child.pid && current2.version === options2.version) {
|
|
31218
31241
|
const client = new CaptureServerClient(current2);
|
|
@@ -31233,6 +31256,7 @@ var CaptureServerClient;
|
|
|
31233
31256
|
var init_client2 = __esm({
|
|
31234
31257
|
"src/capture-server/client.ts"() {
|
|
31235
31258
|
"use strict";
|
|
31259
|
+
init_process();
|
|
31236
31260
|
CaptureServerClient = class {
|
|
31237
31261
|
constructor(receipt, fetcher = fetch) {
|
|
31238
31262
|
this.receipt = receipt;
|
|
@@ -31458,7 +31482,7 @@ function dataRoot(env) {
|
|
|
31458
31482
|
const home = homedir();
|
|
31459
31483
|
if (platform() === "darwin") return join7(home, "Library", "Application Support", "apilift");
|
|
31460
31484
|
if (platform() === "win32") return join7(env.LOCALAPPDATA || join7(home, "AppData", "Local"), "apilift");
|
|
31461
|
-
return join7(env.XDG_DATA_HOME
|
|
31485
|
+
return join7(env.XDG_DATA_HOME && isAbsolute(env.XDG_DATA_HOME) ? env.XDG_DATA_HOME : join7(home, ".local", "share"), "apilift");
|
|
31462
31486
|
}
|
|
31463
31487
|
var LocalState;
|
|
31464
31488
|
var init_state = __esm({
|
|
@@ -33393,30 +33417,58 @@ var init_dist = __esm({
|
|
|
33393
33417
|
});
|
|
33394
33418
|
|
|
33395
33419
|
// src/capture-server/store.ts
|
|
33420
|
+
import { mkdirSync as mkdirSync6, chmodSync as chmodSync6, readFileSync as readFileSync6 } from "node:fs";
|
|
33396
33421
|
import { execFileSync } from "node:child_process";
|
|
33397
33422
|
import { DatabaseSync as DatabaseSync5 } from "node:sqlite";
|
|
33398
|
-
function
|
|
33399
|
-
|
|
33400
|
-
const alive = probe.alive ??
|
|
33401
|
-
|
|
33402
|
-
|
|
33403
|
-
|
|
33404
|
-
} catch {
|
|
33423
|
+
function createOwnerVerifier(probe = {}) {
|
|
33424
|
+
const cached2 = /* @__PURE__ */ new Map();
|
|
33425
|
+
const alive = probe.alive ?? pidAlive, now = probe.now ?? Date.now;
|
|
33426
|
+
return (pid, startedAt, fresh = false) => {
|
|
33427
|
+
if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(startedAt) || !alive(pid)) {
|
|
33428
|
+
cached2.delete(pid);
|
|
33405
33429
|
return false;
|
|
33406
33430
|
}
|
|
33407
|
-
|
|
33408
|
-
|
|
33431
|
+
if ((probe.platform ?? process.platform) === "linux") return inspectOwner(pid, startedAt, probe);
|
|
33432
|
+
const prior = cached2.get(pid), time3 = now();
|
|
33433
|
+
if (!fresh && prior && prior.startedAt === startedAt && time3 >= prior.checkedAt && time3 - prior.checkedAt < 2e3) return true;
|
|
33434
|
+
cached2.delete(pid);
|
|
33435
|
+
if (!inspectOwner(pid, startedAt, probe)) return false;
|
|
33436
|
+
if (cached2.size >= 256) cached2.delete(cached2.keys().next().value);
|
|
33437
|
+
cached2.set(pid, { startedAt, checkedAt: now() });
|
|
33438
|
+
return true;
|
|
33439
|
+
};
|
|
33440
|
+
}
|
|
33441
|
+
function ownerProcessAlive(pid, expectedStartedAt, probe) {
|
|
33442
|
+
return typeof probe === "object" ? inspectOwner(pid, expectedStartedAt, probe) : defaultOwnerVerifier(pid, expectedStartedAt, probe);
|
|
33443
|
+
}
|
|
33444
|
+
function inspectOwner(pid, expectedStartedAt, probe) {
|
|
33445
|
+
if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(expectedStartedAt)) return false;
|
|
33446
|
+
const alive = probe.alive ?? pidAlive;
|
|
33447
|
+
const inspect = probe.inspect ?? inspectProcess;
|
|
33409
33448
|
const platform4 = probe.platform ?? process.platform;
|
|
33410
33449
|
const now = probe.now ?? Date.now;
|
|
33411
33450
|
const started = now();
|
|
33412
33451
|
const windows = platform4 === "win32";
|
|
33452
|
+
if (platform4 === "linux") {
|
|
33453
|
+
try {
|
|
33454
|
+
const read = probe.read ?? ((path2) => readFileSync6(path2, "utf8"));
|
|
33455
|
+
const stat2 = read(`/proc/${pid}/stat`), fields = stat2.slice(stat2.lastIndexOf(")") + 2).trim().split(/\s+/u);
|
|
33456
|
+
if (["Z", "X"].includes(fields[0])) return false;
|
|
33457
|
+
const ticks = Number(fields[19]), boot = Number(/^btime (\d+)$/mu.exec(read("/proc/stat"))?.[1]);
|
|
33458
|
+
const hz = probe.inspect ? Number(inspect("getconf", ["CLK_TCK"], 2e3)) : linuxClockTicks ??= Number(inspect("getconf", ["CLK_TCK"], 2e3));
|
|
33459
|
+
const observed = boot * 1e3 + ticks * 1e3 / hz;
|
|
33460
|
+
return Number.isFinite(observed) && hz > 0 && Math.abs(observed - expectedStartedAt) <= 5e3;
|
|
33461
|
+
} catch {
|
|
33462
|
+
return false;
|
|
33463
|
+
}
|
|
33464
|
+
}
|
|
33413
33465
|
for (let attempt = 0; attempt < (windows ? 2 : 1); attempt++) {
|
|
33414
33466
|
if (!alive(pid)) return false;
|
|
33415
33467
|
const remaining = windows ? 8e3 - (now() - started) : 2e3;
|
|
33416
33468
|
if (remaining <= 0) return false;
|
|
33417
33469
|
try {
|
|
33418
|
-
const raw = windows ? inspect("powershell.exe", ["-NoProfile", "-Command", `(Get-Process -Id ${pid}).StartTime.ToUniversalTime().ToString('o')`], Math.min(4e3, remaining)) : inspect("ps", ["-o", "lstart=", "-p", String(pid)], 2e3);
|
|
33419
|
-
const observed = Date.parse(raw.trim());
|
|
33470
|
+
const raw = windows ? inspect("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", `(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().ToString('o')`], Math.min(4e3, remaining)) : inspect("ps", ["-o", "lstart=", "-p", String(pid)], 2e3);
|
|
33471
|
+
const observed = Date.parse(windows ? raw.trim() : `${raw.trim()} UTC`);
|
|
33420
33472
|
return Number.isFinite(observed) && Math.abs(observed - expectedStartedAt) <= 5e3;
|
|
33421
33473
|
} catch (error62) {
|
|
33422
33474
|
if (!windows || error62.code !== "ETIMEDOUT") return false;
|
|
@@ -33424,25 +33476,36 @@ function ownerProcessAlive(pid, expectedStartedAt, probe = {}) {
|
|
|
33424
33476
|
}
|
|
33425
33477
|
return false;
|
|
33426
33478
|
}
|
|
33479
|
+
var pidAlive, inspectProcess, linuxClockTicks, defaultOwnerVerifier;
|
|
33427
33480
|
var init_store = __esm({
|
|
33428
33481
|
"src/capture-server/store.ts"() {
|
|
33429
33482
|
"use strict";
|
|
33430
33483
|
init_dist();
|
|
33484
|
+
pidAlive = (candidate2) => {
|
|
33485
|
+
try {
|
|
33486
|
+
process.kill(candidate2, 0);
|
|
33487
|
+
return true;
|
|
33488
|
+
} catch {
|
|
33489
|
+
return false;
|
|
33490
|
+
}
|
|
33491
|
+
};
|
|
33492
|
+
inspectProcess = (command6, args, timeout) => execFileSync(command6, args, { encoding: "utf8", timeout, windowsHide: true, env: { ...process.env, LC_ALL: "C", TZ: "UTC" }, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
33493
|
+
defaultOwnerVerifier = createOwnerVerifier();
|
|
33431
33494
|
}
|
|
33432
33495
|
});
|
|
33433
33496
|
|
|
33434
33497
|
// src/discovery/lock.ts
|
|
33435
33498
|
import { createHash as createHash3 } from "node:crypto";
|
|
33436
|
-
import { mkdirSync as
|
|
33499
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync7, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
33437
33500
|
import { join as join10 } from "node:path";
|
|
33438
33501
|
function lockDiscovery(root, sessionId) {
|
|
33439
33502
|
const name = createHash3("sha256").update(sessionId).digest("hex");
|
|
33440
33503
|
const directory = join10(root, "locks", `discovery-${name}`);
|
|
33441
|
-
|
|
33504
|
+
mkdirSync7(join10(root, "locks"), { recursive: true, mode: 448 });
|
|
33442
33505
|
const owner = { pid: process.pid, startedAt: Date.now() - process.uptime() * 1e3 };
|
|
33443
33506
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
33444
33507
|
try {
|
|
33445
|
-
|
|
33508
|
+
mkdirSync7(directory, { mode: 448 });
|
|
33446
33509
|
writeFileSync6(join10(directory, "owner.json"), JSON.stringify(owner), { flag: "wx", mode: 384 });
|
|
33447
33510
|
return () => {
|
|
33448
33511
|
rmSync3(directory, { recursive: true, force: true });
|
|
@@ -33451,7 +33514,7 @@ function lockDiscovery(root, sessionId) {
|
|
|
33451
33514
|
if (error62.code !== "EEXIST") throw error62;
|
|
33452
33515
|
let held = null;
|
|
33453
33516
|
try {
|
|
33454
|
-
held = JSON.parse(
|
|
33517
|
+
held = JSON.parse(readFileSync7(join10(directory, "owner.json"), "utf8"));
|
|
33455
33518
|
} catch {
|
|
33456
33519
|
}
|
|
33457
33520
|
if (!held || ownerProcessAlive(held.pid, held.startedAt)) throw new Error("discovery-command-busy \u2014 This agent already has a discovery command running; wait for it to finish, then retry");
|
|
@@ -33495,7 +33558,7 @@ var init_session = __esm({
|
|
|
33495
33558
|
});
|
|
33496
33559
|
|
|
33497
33560
|
// src/commands/discover.ts
|
|
33498
|
-
import { existsSync as existsSync3, mkdirSync as
|
|
33561
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, renameSync as renameSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
33499
33562
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
33500
33563
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
33501
33564
|
import { dirname as dirname5, join as join11 } from "node:path";
|
|
@@ -33654,7 +33717,7 @@ ${local}When ready to test the configured request: ${command4(invocation, "disco
|
|
|
33654
33717
|
For browser observation: ${command4(invocation, "discover capture start")}
|
|
33655
33718
|
`;
|
|
33656
33719
|
if (draft.kind === "transport") {
|
|
33657
|
-
const browser = parseDraftEnvelope(
|
|
33720
|
+
const browser = parseDraftEnvelope(readFileSync8(draft.filePath, "utf8")).envelope?.definition.mode === "browser";
|
|
33658
33721
|
const browserAuth = browser ? `
|
|
33659
33722
|
For a page-derived authentication value, place its observed locator under definition.inject[].from and the destination under definition.inject[].to. Example invented notes app definition fragment: ${JSON.stringify(browserLocatorExample)}. definition.credentials is only for separately saved human-provided secrets; leave it [] when browser login supplies access. Never copy a token value. Verify the harmless read before accepting the recipe.
|
|
33660
33723
|
` : "";
|
|
@@ -33698,7 +33761,7 @@ File: ${selected.filePath}
|
|
|
33698
33761
|
if (draft.intent === "remove" && store.publication(draft.id)) return fail5(`A removal publication may have been sent. Reconcile its retained request with ${command4(invocation, "discover publish")} before changing, deferring or discarding it.
|
|
33699
33762
|
File: ${draft.filePath}
|
|
33700
33763
|
`, 12);
|
|
33701
|
-
if (resource &&
|
|
33764
|
+
if (resource && readFileSync8(draft.filePath, "utf8") === draftTemplate(kind)) {
|
|
33702
33765
|
const definition2 = resource.definition;
|
|
33703
33766
|
const dependencies = kind === "action" && !("unavailable" in definition2) ? { transport: String(definition2.transport ?? "") } : kind === "transport" && definition2.browserContext ? { browserPage: String(definition2.browserContext) } : void 0;
|
|
33704
33767
|
const editable = { definition: definition2, ...dependencies ? { dependencies } : {}, ...kind === "action" && !("unavailable" in definition2) || kind === "transport" ? { verification: { inputs: {}, review: "pending", notes: "" } } : {} };
|
|
@@ -33706,7 +33769,7 @@ File: ${draft.filePath}
|
|
|
33706
33769
|
`, { mode: 384 });
|
|
33707
33770
|
}
|
|
33708
33771
|
void root;
|
|
33709
|
-
return ok4(draftGuidance(invocation, draft, Boolean(parseDraftEnvelope(
|
|
33772
|
+
return ok4(draftGuidance(invocation, draft, Boolean(parseDraftEnvelope(readFileSync8(draft.filePath, "utf8")).envelope?.definition.unavailable)));
|
|
33710
33773
|
}
|
|
33711
33774
|
function requireDiscovery(store, session, invocation) {
|
|
33712
33775
|
const current = store.session(session.id);
|
|
@@ -33733,7 +33796,7 @@ function handleResearch(invocation, state, store, session, root) {
|
|
|
33733
33796
|
return fail5(`${error62 instanceof Error ? error62.message : "Invalid research scope"}.
|
|
33734
33797
|
`);
|
|
33735
33798
|
}
|
|
33736
|
-
|
|
33799
|
+
mkdirSync8(dirname5(path2), { recursive: true, mode: 448 });
|
|
33737
33800
|
if (!existsSync3(path2)) writeFileSync7(path2, `// Record a focused check of official operation and access documentation.
|
|
33738
33801
|
${JSON.stringify({ scope: scope2, conclusion: "pending", findings: "", sources: [{ kind: "operation", url: "", finding: "" }, { kind: "access", url: "", finding: "" }] }, null, 2)}
|
|
33739
33802
|
`, { flag: "wx", mode: 384 });
|
|
@@ -33767,7 +33830,7 @@ If newer official docs change a finding, edit its file and run ${command4(invoca
|
|
|
33767
33830
|
const selection = state.db.prepare("SELECT r.* FROM discovery_research r JOIN selected_discovery_research s ON s.app_slug=r.app_slug AND s.scope=r.scope WHERE s.session_id=?").get(session.id);
|
|
33768
33831
|
if (!selection) return fail5(`No API research file is selected. Start with ${command4(invocation, "discover api assess <action-or-app>")}.
|
|
33769
33832
|
`);
|
|
33770
|
-
const source =
|
|
33833
|
+
const source = readFileSync8(selection.file_path, "utf8"), errors = [];
|
|
33771
33834
|
const seen = [], duplicates = [];
|
|
33772
33835
|
visit3(source, { onObjectBegin: () => {
|
|
33773
33836
|
seen.push(/* @__PURE__ */ new Set());
|
|
@@ -34194,7 +34257,7 @@ async function rebaseDraft(invocation, api, store, session) {
|
|
|
34194
34257
|
if (draft.intent === "remove") {
|
|
34195
34258
|
const checked = await checkDraft(store, session.id, api);
|
|
34196
34259
|
if (checked.issues.length) return checkResponse(checked, invocation);
|
|
34197
|
-
const source =
|
|
34260
|
+
const source = readFileSync8(draft.filePath, "utf8");
|
|
34198
34261
|
const updated = applyEdits(source, modify(source, ["expectedVersion"], current.version, { formattingOptions: { insertSpaces: true, tabSize: 2 } }));
|
|
34199
34262
|
const temporary = `${draft.filePath}.${randomUUID8()}.tmp`;
|
|
34200
34263
|
writeFileSync7(temporary, updated, { flag: "wx", mode: 384 });
|
|
@@ -34826,715 +34889,769 @@ var init_output = __esm({
|
|
|
34826
34889
|
}
|
|
34827
34890
|
});
|
|
34828
34891
|
|
|
34829
|
-
//
|
|
34830
|
-
import {
|
|
34831
|
-
import {
|
|
34832
|
-
import {
|
|
34833
|
-
import { homedir as homedir2 } from "node:os";
|
|
34834
|
-
import { dirname as dirname6, join as join13, resolve as resolve2 } from "node:path";
|
|
34892
|
+
// ../../node_modules/.pnpm/tinyexec@1.3.1/node_modules/tinyexec/dist/main.mjs
|
|
34893
|
+
import { spawn as spawn2, spawnSync } from "node:child_process";
|
|
34894
|
+
import { cwd } from "node:process";
|
|
34895
|
+
import { basename, delimiter, dirname as dirname6, normalize, resolve as resolve2 } from "node:path";
|
|
34835
34896
|
import { fileURLToPath } from "node:url";
|
|
34836
|
-
|
|
34837
|
-
|
|
34838
|
-
|
|
34839
|
-
|
|
34840
|
-
|
|
34897
|
+
import { pipeline } from "node:stream/promises";
|
|
34898
|
+
import { PassThrough } from "node:stream";
|
|
34899
|
+
import readline from "node:readline";
|
|
34900
|
+
import { closeSync, openSync, readSync, statSync } from "node:fs";
|
|
34901
|
+
function getPathFromEnv(env) {
|
|
34902
|
+
for (const key in env) {
|
|
34903
|
+
if (!Object.prototype.hasOwnProperty.call(env, key) || !isPathLikePattern.test(key)) continue;
|
|
34904
|
+
const value = env[key];
|
|
34905
|
+
if (!value) return defaultEnvPathInfo;
|
|
34906
|
+
return {
|
|
34907
|
+
key,
|
|
34908
|
+
value
|
|
34909
|
+
};
|
|
34910
|
+
}
|
|
34911
|
+
return defaultEnvPathInfo;
|
|
34841
34912
|
}
|
|
34842
|
-
function
|
|
34843
|
-
|
|
34844
|
-
|
|
34845
|
-
|
|
34846
|
-
|
|
34913
|
+
function addNodeBinToPath(cwd2, path2) {
|
|
34914
|
+
const parts = path2.value.split(delimiter);
|
|
34915
|
+
const nodeBinPaths = [];
|
|
34916
|
+
let currentPath = typeof cwd2 === "string" ? cwd2 : fileURLToPath(cwd2, { windows: false });
|
|
34917
|
+
let lastPath;
|
|
34918
|
+
do {
|
|
34919
|
+
nodeBinPaths.push(resolve2(currentPath, "node_modules", ".bin"));
|
|
34920
|
+
lastPath = currentPath;
|
|
34921
|
+
currentPath = dirname6(currentPath);
|
|
34922
|
+
} while (currentPath !== lastPath);
|
|
34923
|
+
nodeBinPaths.push(dirname6(process.execPath));
|
|
34924
|
+
const newPath = nodeBinPaths.concat(parts).join(delimiter);
|
|
34925
|
+
return {
|
|
34926
|
+
key: path2.key,
|
|
34927
|
+
value: newPath
|
|
34928
|
+
};
|
|
34847
34929
|
}
|
|
34848
|
-
function
|
|
34849
|
-
const
|
|
34850
|
-
|
|
34851
|
-
|
|
34930
|
+
function computeEnv(cwd2, env, nodePath = true) {
|
|
34931
|
+
const envWithDefault = {
|
|
34932
|
+
...process.env,
|
|
34933
|
+
...env
|
|
34934
|
+
};
|
|
34935
|
+
if (!nodePath) return envWithDefault;
|
|
34936
|
+
const envPathInfo = addNodeBinToPath(cwd2, getPathFromEnv(envWithDefault));
|
|
34937
|
+
envWithDefault[envPathInfo.key] = envPathInfo.value;
|
|
34938
|
+
return envWithDefault;
|
|
34852
34939
|
}
|
|
34853
|
-
function
|
|
34854
|
-
|
|
34855
|
-
|
|
34856
|
-
|
|
34940
|
+
function normalizeSpawnCommand(command6, args = [], options2 = {}) {
|
|
34941
|
+
if (options2.shell === true || !isWindows) return {
|
|
34942
|
+
command: command6,
|
|
34943
|
+
args,
|
|
34944
|
+
options: options2
|
|
34945
|
+
};
|
|
34946
|
+
let file2 = resolveCommand(command6, options2);
|
|
34947
|
+
let shebang = null;
|
|
34948
|
+
if (file2 !== null) {
|
|
34949
|
+
const size = 150;
|
|
34950
|
+
const buffer = Buffer.alloc(size);
|
|
34951
|
+
let fd = null;
|
|
34952
|
+
try {
|
|
34953
|
+
fd = openSync(file2, "r");
|
|
34954
|
+
readSync(fd, buffer, 0, size, 0);
|
|
34955
|
+
} catch {
|
|
34956
|
+
} finally {
|
|
34957
|
+
if (fd !== null) closeSync(fd);
|
|
34958
|
+
}
|
|
34959
|
+
const match = buffer.toString().match(shebangRegExp);
|
|
34960
|
+
if (match !== null) {
|
|
34961
|
+
const line = match[1].trim();
|
|
34962
|
+
const separatorIndex = line.indexOf(" ");
|
|
34963
|
+
const path2 = separatorIndex !== -1 ? line.slice(0, separatorIndex) : line;
|
|
34964
|
+
const argument = separatorIndex !== -1 ? line.slice(separatorIndex + 1) : "";
|
|
34965
|
+
const binary = basename(path2);
|
|
34966
|
+
shebang = binary === "env" ? argument || null : binary;
|
|
34967
|
+
}
|
|
34968
|
+
}
|
|
34969
|
+
if (shebang !== null && file2 !== null) {
|
|
34970
|
+
args = [file2, ...args];
|
|
34971
|
+
command6 = shebang;
|
|
34972
|
+
file2 = resolveCommand(command6, options2);
|
|
34973
|
+
}
|
|
34974
|
+
if (file2 === null || !isWindowsExecutableRegExp.test(file2)) {
|
|
34975
|
+
const needsDoubleEscapeMetaChars = file2 !== null && isNodeModulesCmdRegExp.test(file2);
|
|
34976
|
+
command6 = normalize(command6);
|
|
34977
|
+
command6 = command6.replace(metaCharsRegExp, "^$1");
|
|
34978
|
+
args = args.map((arg) => {
|
|
34979
|
+
arg = arg.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
34980
|
+
arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
34981
|
+
arg = `"${arg}"`;
|
|
34982
|
+
arg = arg.replace(metaCharsRegExp, "^$1");
|
|
34983
|
+
if (needsDoubleEscapeMetaChars) arg = arg.replace(metaCharsRegExp, "^$1");
|
|
34984
|
+
return arg;
|
|
34985
|
+
});
|
|
34986
|
+
args = [
|
|
34987
|
+
"/d",
|
|
34988
|
+
"/s",
|
|
34989
|
+
"/c",
|
|
34990
|
+
`"${[command6, ...args].join(" ")}"`
|
|
34991
|
+
];
|
|
34992
|
+
command6 = options2.env?.comspec ?? "cmd.exe";
|
|
34993
|
+
options2 = {
|
|
34994
|
+
...options2,
|
|
34995
|
+
windowsVerbatimArguments: true
|
|
34996
|
+
};
|
|
34997
|
+
}
|
|
34998
|
+
return {
|
|
34999
|
+
command: command6,
|
|
35000
|
+
args,
|
|
35001
|
+
options: options2
|
|
35002
|
+
};
|
|
34857
35003
|
}
|
|
34858
|
-
function
|
|
34859
|
-
|
|
34860
|
-
|
|
34861
|
-
|
|
34862
|
-
|
|
35004
|
+
function resolveCommand(command6, options2) {
|
|
35005
|
+
const cwd$3 = (options2.cwd ?? cwd()).toString();
|
|
35006
|
+
const env = options2.env ?? process.env;
|
|
35007
|
+
const PATH = getPathFromEnv(env).value;
|
|
35008
|
+
const pathEnv = command6.includes("/") || command6.includes("\\") ? [""] : [cwd$3, ...PATH.split(delimiter)];
|
|
35009
|
+
let pathExt = env.PATHEXT ? env.PATHEXT.split(delimiter) : defaultPathExt;
|
|
35010
|
+
if (command6.includes(".") && pathExt[0] !== "") pathExt = ["", ...pathExt];
|
|
35011
|
+
for (const extensions of [pathExt, noPathExt]) for (const path2 of pathEnv) {
|
|
35012
|
+
const unquoted = path2.startsWith('"') && path2.endsWith('"') && path2.length > 1 ? path2.slice(1, -1) : path2;
|
|
35013
|
+
const dest = resolve2(cwd$3, unquoted, command6);
|
|
35014
|
+
for (const ext of extensions) {
|
|
35015
|
+
const destWithExt = dest + ext;
|
|
35016
|
+
try {
|
|
35017
|
+
if (statSync(destWithExt).isFile()) return destWithExt;
|
|
35018
|
+
} catch {
|
|
35019
|
+
}
|
|
35020
|
+
}
|
|
34863
35021
|
}
|
|
35022
|
+
return null;
|
|
34864
35023
|
}
|
|
34865
|
-
function
|
|
34866
|
-
const
|
|
34867
|
-
|
|
34868
|
-
|
|
34869
|
-
|
|
34870
|
-
|
|
35024
|
+
function combineSignals(signals) {
|
|
35025
|
+
const controller = new AbortController();
|
|
35026
|
+
for (const signal of signals) {
|
|
35027
|
+
if (signal.aborted) {
|
|
35028
|
+
controller.abort();
|
|
35029
|
+
return signal;
|
|
35030
|
+
}
|
|
35031
|
+
const onAbort = () => {
|
|
35032
|
+
controller.abort(signal.reason);
|
|
35033
|
+
};
|
|
35034
|
+
signal.addEventListener("abort", onAbort, { signal: controller.signal });
|
|
34871
35035
|
}
|
|
35036
|
+
return controller.signal;
|
|
34872
35037
|
}
|
|
34873
|
-
function
|
|
34874
|
-
|
|
35038
|
+
async function readStream(stream) {
|
|
35039
|
+
let output2 = "";
|
|
34875
35040
|
try {
|
|
34876
|
-
const
|
|
34877
|
-
|
|
34878
|
-
if (!Array.isArray(entries) || entries.some((entry2) => typeof entry2 !== "object" || entry2 === null || typeof (agent2 === "codex" ? entry2.pluginId : entry2.id) !== "string")) return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: plugin list returned an unexpected response` };
|
|
34879
|
-
const plugin = entries.find((entry2) => (agent2 === "codex" ? entry2.pluginId : entry2.id) === "apilift@personal");
|
|
34880
|
-
if (!plugin) return { ready: false, known: true, detail: "Apilift is not installed in this agent" };
|
|
34881
|
-
if (typeof plugin.enabled !== "boolean" || typeof plugin.version !== "string") return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: Apilift status is incomplete` };
|
|
34882
|
-
if (!plugin.enabled) return { ready: false, known: true, detail: "Apilift is disabled in this agent" };
|
|
34883
|
-
if (plugin.version !== expected) return { ready: false, known: true, detail: "The active Apilift plugin does not match the packaged version" };
|
|
34884
|
-
return { ready: true, known: true, detail: "Apilift setup, use and discovery skills are active" };
|
|
34885
|
-
} catch (error62) {
|
|
34886
|
-
const code = typeof error62 === "object" && error62 && "code" in error62 ? error62.code : void 0;
|
|
34887
|
-
const reason = code === "ETIMEDOUT" ? "plugin list timed out after 10 seconds" : code === "ENOENT" ? `${agent2} executable was not found` : "plugin list failed";
|
|
34888
|
-
return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: ${reason}` };
|
|
35041
|
+
for await (const chunk of stream) output2 += chunk.toString();
|
|
35042
|
+
} catch {
|
|
34889
35043
|
}
|
|
35044
|
+
return output2;
|
|
34890
35045
|
}
|
|
34891
|
-
function
|
|
34892
|
-
|
|
34893
|
-
|
|
34894
|
-
|
|
34895
|
-
|
|
34896
|
-
const
|
|
34897
|
-
|
|
34898
|
-
|
|
34899
|
-
|
|
34900
|
-
const
|
|
34901
|
-
|
|
34902
|
-
|
|
34903
|
-
const
|
|
34904
|
-
|
|
34905
|
-
if (
|
|
34906
|
-
const
|
|
34907
|
-
|
|
35046
|
+
function xSync(command6, args, options2) {
|
|
35047
|
+
const opts = {
|
|
35048
|
+
...defaultSyncOptions,
|
|
35049
|
+
...options2
|
|
35050
|
+
};
|
|
35051
|
+
const nodeOptions = {
|
|
35052
|
+
...defaultNodeOptions,
|
|
35053
|
+
...opts.nodeOptions
|
|
35054
|
+
};
|
|
35055
|
+
const cwd$2 = nodeOptions?.cwd ?? cwd();
|
|
35056
|
+
if (opts.timeout !== void 0) nodeOptions.timeout = opts.timeout;
|
|
35057
|
+
nodeOptions.env = computeEnv(cwd$2, nodeOptions.env, opts.nodePath);
|
|
35058
|
+
const crossResult = normalizeSpawnCommand(command6, args ?? [], nodeOptions);
|
|
35059
|
+
const spawnResult = spawnSync(crossResult.command, crossResult.args, crossResult.options);
|
|
35060
|
+
if (spawnResult.error) throw spawnResult.error;
|
|
35061
|
+
const stdout = spawnResult.stdout?.toString() ?? "";
|
|
35062
|
+
const stderr = spawnResult.stderr?.toString() ?? "";
|
|
35063
|
+
const exitCode = spawnResult.status ?? void 0;
|
|
35064
|
+
const signalCode = spawnResult.signal ?? null;
|
|
35065
|
+
const killed = signalCode !== null;
|
|
35066
|
+
const result3 = {
|
|
35067
|
+
stdout,
|
|
35068
|
+
stderr,
|
|
35069
|
+
get exitCode() {
|
|
35070
|
+
return exitCode;
|
|
35071
|
+
},
|
|
35072
|
+
get signalCode() {
|
|
35073
|
+
return signalCode;
|
|
35074
|
+
},
|
|
35075
|
+
get pid() {
|
|
35076
|
+
return spawnResult.pid;
|
|
35077
|
+
},
|
|
35078
|
+
get killed() {
|
|
35079
|
+
return killed;
|
|
35080
|
+
},
|
|
35081
|
+
*[Symbol.iterator]() {
|
|
35082
|
+
for (const text2 of [stdout, stderr]) {
|
|
35083
|
+
if (!text2) continue;
|
|
35084
|
+
const lines = text2.split(LINE_SEPARATOR_REGEX);
|
|
35085
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
35086
|
+
yield* lines;
|
|
35087
|
+
}
|
|
35088
|
+
}
|
|
35089
|
+
};
|
|
35090
|
+
if (opts.throwOnError && (exitCode !== 0 && exitCode !== void 0 || signalCode !== null)) throw new NonZeroExitError(result3, {
|
|
35091
|
+
stdout: result3.stdout,
|
|
35092
|
+
stderr: result3.stderr,
|
|
35093
|
+
exitCode: result3.exitCode
|
|
35094
|
+
}, command6, args);
|
|
35095
|
+
return result3;
|
|
34908
35096
|
}
|
|
34909
|
-
|
|
34910
|
-
|
|
34911
|
-
|
|
34912
|
-
|
|
34913
|
-
|
|
34914
|
-
|
|
34915
|
-
|
|
34916
|
-
|
|
34917
|
-
|
|
34918
|
-
|
|
34919
|
-
|
|
34920
|
-
|
|
34921
|
-
|
|
34922
|
-
|
|
34923
|
-
|
|
34924
|
-
|
|
34925
|
-
|
|
34926
|
-
|
|
34927
|
-
|
|
34928
|
-
|
|
34929
|
-
|
|
34930
|
-
|
|
34931
|
-
|
|
34932
|
-
|
|
34933
|
-
|
|
34934
|
-
|
|
34935
|
-
|
|
34936
|
-
|
|
34937
|
-
|
|
34938
|
-
|
|
34939
|
-
|
|
34940
|
-
|
|
34941
|
-
|
|
34942
|
-
|
|
34943
|
-
|
|
34944
|
-
|
|
34945
|
-
|
|
34946
|
-
|
|
34947
|
-
|
|
34948
|
-
|
|
34949
|
-
|
|
34950
|
-
|
|
34951
|
-
|
|
34952
|
-
|
|
34953
|
-
|
|
34954
|
-
|
|
34955
|
-
|
|
34956
|
-
|
|
34957
|
-
|
|
34958
|
-
writeJson(join13(marketplace, ".claude-plugin", "marketplace.json"), { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name: "personal", description: "Personal agent plugins", owner: { name: "Local" }, plugins: [{ name: "apilift", description: "Use logged-in apps and discover missing actions with Apilift", source: "./plugins/apilift", category: "development" }] });
|
|
34959
|
-
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: `Plugin staged at ${plugin}; activation is disabled` };
|
|
34960
|
-
const initial = active(agent2, expected);
|
|
34961
|
-
if (!initial.known) return { ready: false, version: expected, detail: initial.detail, checkFailed: true };
|
|
34962
|
-
if (initial.ready) return { ready: true, version: expected, detail: initial.detail };
|
|
34963
|
-
{
|
|
34964
|
-
if (agent2 === "codex") command5("codex", ["plugin", "add", "apilift@personal"]);
|
|
34965
|
-
else {
|
|
34966
|
-
let marketplaces;
|
|
34967
|
-
try {
|
|
34968
|
-
marketplaces = command5("claude", ["plugin", "marketplace", "list", "--json"]);
|
|
34969
|
-
} catch {
|
|
34970
|
-
marketplaces = [];
|
|
35097
|
+
var isPathLikePattern, defaultEnvPathInfo, combineStreams, metaCharsRegExp, shebangRegExp, isWindowsExecutableRegExp, isNodeModulesCmdRegExp, isWindows, defaultPathExt, noPathExt, NonZeroExitError, LINE_SEPARATOR_REGEX, defaultOptions, defaultSyncOptions, defaultNodeOptions, ExecProcess, x, exec;
|
|
35098
|
+
var init_main2 = __esm({
|
|
35099
|
+
"../../node_modules/.pnpm/tinyexec@1.3.1/node_modules/tinyexec/dist/main.mjs"() {
|
|
35100
|
+
isPathLikePattern = /^path$/i;
|
|
35101
|
+
defaultEnvPathInfo = {
|
|
35102
|
+
key: "PATH",
|
|
35103
|
+
value: ""
|
|
35104
|
+
};
|
|
35105
|
+
combineStreams = (streams) => {
|
|
35106
|
+
let streamCount = streams.length;
|
|
35107
|
+
const combined = new PassThrough();
|
|
35108
|
+
const maybeEmitEnd = () => {
|
|
35109
|
+
if (--streamCount === 0) combined.end();
|
|
35110
|
+
};
|
|
35111
|
+
for (const stream of streams) pipeline(stream, combined, { end: false }).then(maybeEmitEnd).catch(maybeEmitEnd);
|
|
35112
|
+
return combined;
|
|
35113
|
+
};
|
|
35114
|
+
metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
|
|
35115
|
+
shebangRegExp = /^#!\s*(.+)/;
|
|
35116
|
+
isWindowsExecutableRegExp = /\.(?:com|exe)$/i;
|
|
35117
|
+
isNodeModulesCmdRegExp = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i;
|
|
35118
|
+
isWindows = process.platform === "win32";
|
|
35119
|
+
defaultPathExt = [
|
|
35120
|
+
".EXE",
|
|
35121
|
+
".CMD",
|
|
35122
|
+
".BAT",
|
|
35123
|
+
".COM"
|
|
35124
|
+
];
|
|
35125
|
+
noPathExt = [""];
|
|
35126
|
+
NonZeroExitError = class extends Error {
|
|
35127
|
+
result;
|
|
35128
|
+
output;
|
|
35129
|
+
exitCode;
|
|
35130
|
+
get signalCode() {
|
|
35131
|
+
return this.result.signalCode;
|
|
35132
|
+
}
|
|
35133
|
+
constructor(result3, output2, command6, args) {
|
|
35134
|
+
let target = "The process";
|
|
35135
|
+
if (command6) target = `The command \`${args?.length ? `${command6} ${args.map((a) => /[ "'`()]/.test(a) ? JSON.stringify(a) : a).join(" ")}` : command6}\``;
|
|
35136
|
+
const exitCode = result3.exitCode ?? 1;
|
|
35137
|
+
super(result3.signalCode !== null ? `${target} was killed by the signal ${result3.signalCode}` : `${target} exited with a non-zero status (${exitCode})`);
|
|
35138
|
+
this.result = result3;
|
|
35139
|
+
this.output = output2;
|
|
35140
|
+
this.exitCode = exitCode;
|
|
35141
|
+
Object.defineProperty(this, "result", {
|
|
35142
|
+
enumerable: false,
|
|
35143
|
+
writable: false,
|
|
35144
|
+
configurable: false
|
|
35145
|
+
});
|
|
34971
35146
|
}
|
|
34972
|
-
if (!Array.isArray(marketplaces) || !marketplaces.some((item) => typeof item === "object" && item !== null && item.name === "personal")) command5("claude", ["plugin", "marketplace", "add", marketplace, "--scope", "user"]);
|
|
34973
|
-
const listed = command5("claude", ["plugin", "list", "--json"]);
|
|
34974
|
-
const installed = Array.isArray(listed) && listed.some((item) => typeof item === "object" && item !== null && item.id === "apilift@personal");
|
|
34975
|
-
command5("claude", ["plugin", installed ? "update" : "install", "apilift@personal", "--scope", "user"]);
|
|
34976
|
-
command5("claude", ["plugin", "enable", "apilift@personal", "--scope", "user"]);
|
|
34977
|
-
}
|
|
34978
|
-
}
|
|
34979
|
-
const activation = active(agent2, expected);
|
|
34980
|
-
return { ready: activation.ready, version: expected, detail: activation.detail, checkFailed: !activation.known };
|
|
34981
|
-
}
|
|
34982
|
-
var markerName, skillNames;
|
|
34983
|
-
var init_plugin = __esm({
|
|
34984
|
-
"src/plugin.ts"() {
|
|
34985
|
-
"use strict";
|
|
34986
|
-
markerName = ".apilift-managed.json";
|
|
34987
|
-
skillNames = ["setup", "use", "discover"];
|
|
34988
|
-
}
|
|
34989
|
-
});
|
|
34990
|
-
|
|
34991
|
-
// ../../packages/core/dist/analytics/index.js
|
|
34992
|
-
function normalizeRoute(route) {
|
|
34993
|
-
try {
|
|
34994
|
-
const parsed = new URL(route, "https://apilift.dev");
|
|
34995
|
-
return parsed.pathname.replace(/^\/dashboard\/apps\/[^/]+/, "/dashboard/apps/:app").replace(uuid5, ":id").replace(longId, ":id");
|
|
34996
|
-
} catch {
|
|
34997
|
-
return "/invalid";
|
|
34998
|
-
}
|
|
34999
|
-
}
|
|
35000
|
-
function scrubEventProperties(event, input2) {
|
|
35001
|
-
const allowed = eventProperties[event];
|
|
35002
|
-
const result3 = {};
|
|
35003
|
-
for (const [key, value] of Object.entries(input2)) {
|
|
35004
|
-
if (!allowed.includes(key))
|
|
35005
|
-
continue;
|
|
35006
|
-
const normalized = key === "route" && typeof value === "string" ? normalizeRoute(value) : value;
|
|
35007
|
-
if (typeof normalized === "boolean" || typeof normalized === "number" && Number.isFinite(normalized) || typeof normalized === "string" && safeString.test(normalized))
|
|
35008
|
-
result3[key] = normalized;
|
|
35009
|
-
}
|
|
35010
|
-
return result3;
|
|
35011
|
-
}
|
|
35012
|
-
var eventProperties, safeString, uuid5, longId;
|
|
35013
|
-
var init_analytics = __esm({
|
|
35014
|
-
"../../packages/core/dist/analytics/index.js"() {
|
|
35015
|
-
"use strict";
|
|
35016
|
-
eventProperties = {
|
|
35017
|
-
"$pageview": ["route"],
|
|
35018
|
-
navigation_clicked: ["route", "target"],
|
|
35019
|
-
pricing_viewed: ["route"],
|
|
35020
|
-
catalog_viewed: ["route"],
|
|
35021
|
-
app_page_viewed: ["route"],
|
|
35022
|
-
onboarding_entered: ["route"],
|
|
35023
|
-
broken_page_viewed: ["route"],
|
|
35024
|
-
authentication_started: ["source", "stage"],
|
|
35025
|
-
authentication_code_sent: ["source", "stage"],
|
|
35026
|
-
authentication_completed: ["source", "stage"],
|
|
35027
|
-
authentication_failed: ["source", "stage", "code"],
|
|
35028
|
-
onboarding_attempt_started: ["attempt_id", "agent", "stage", "outcome", "source", "target"],
|
|
35029
|
-
onboarding_stage_viewed: ["attempt_id", "agent", "stage"],
|
|
35030
|
-
setup_prompt_copied: ["attempt_id", "agent", "stage"],
|
|
35031
|
-
onboarding_next_action_selected: ["attempt_id", "agent", "target"],
|
|
35032
|
-
onboarding_failed: ["stage", "attempt_id", "code", "outcome", "duration_ms"],
|
|
35033
|
-
checkout_requested: ["plan", "interval", "stage", "source"],
|
|
35034
|
-
checkout_ui_changed: ["plan", "interval", "stage", "source"],
|
|
35035
|
-
billing_portal_requested: ["source"],
|
|
35036
|
-
paid_feature_viewed: ["code", "route"],
|
|
35037
|
-
paid_feature_upgrade_opened: ["code", "route"],
|
|
35038
|
-
account_created: [],
|
|
35039
|
-
account_deleted: [],
|
|
35040
|
-
agent_selected: ["agent", "attempt_id", "status"],
|
|
35041
|
-
device_authorization_changed: ["agent", "attempt_id", "status"],
|
|
35042
|
-
onboarding_stage_completed: ["stage", "active", "agent"],
|
|
35043
|
-
installation_readiness_changed: ["stage", "active", "agent"],
|
|
35044
|
-
app_made_public: ["app_id"],
|
|
35045
|
-
execution_finished: ["app_id", "action_id", "outcome", "duration_ms", "http_status", "agent", "purpose"],
|
|
35046
|
-
activation_changed: ["activated"],
|
|
35047
|
-
execution_classified: ["purpose", "revision"],
|
|
35048
|
-
value_snapshot: ["saved_time_ms", "saved_tokens", "saved_value_microusd", "saved_time_ms_available", "saved_tokens_available", "saved_value_microusd_available"],
|
|
35049
|
-
trial_started: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35050
|
-
trial_progress: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35051
|
-
trial_expired: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35052
|
-
trial_completed: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35053
|
-
payment_completed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35054
|
-
payment_status_changed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35055
|
-
payment_failed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35056
|
-
subscription_changed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35057
|
-
payment_adjusted: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35058
|
-
critical_failure: ["code", "count"],
|
|
35059
|
-
cli_command_finished: ["command", "purpose", "outcome", "duration_ms", "stage", "agent"],
|
|
35060
|
-
setup_stage_changed: ["stage", "agent"],
|
|
35061
|
-
discovery_started: ["purpose", "agent"],
|
|
35062
|
-
discovery_finished: ["purpose", "outcome", "duration_ms", "agent"],
|
|
35063
|
-
client_exception: ["code"],
|
|
35064
|
-
native_host_connected: [],
|
|
35065
|
-
native_host_failure: ["code", "operation", "stage", "origin", "failure_count", "duration_ms"],
|
|
35066
|
-
native_host_recovered: ["operation", "stage", "origin", "failure_count", "duration_ms"],
|
|
35067
|
-
extension_installed: ["stage"],
|
|
35068
|
-
extension_connected: ["stage"],
|
|
35069
|
-
extension_disconnected: ["stage"],
|
|
35070
|
-
extension_failure: ["code"],
|
|
35071
|
-
extension_interaction: ["stage", "outcome"],
|
|
35072
|
-
credential_setup_finished: ["stage", "outcome", "code"],
|
|
35073
|
-
"$exception": ["route", "method", "exception_type", "exception_frames", "exception_handled", "exception_level"]
|
|
35074
35147
|
};
|
|
35075
|
-
|
|
35076
|
-
|
|
35077
|
-
|
|
35078
|
-
|
|
35079
|
-
}
|
|
35080
|
-
|
|
35081
|
-
|
|
35082
|
-
|
|
35083
|
-
|
|
35084
|
-
|
|
35085
|
-
|
|
35086
|
-
|
|
35087
|
-
|
|
35088
|
-
|
|
35089
|
-
|
|
35090
|
-
|
|
35091
|
-
|
|
35092
|
-
|
|
35093
|
-
constructor(state, release = "1.0.0", fetcher = fetch) {
|
|
35094
|
-
this.state = state;
|
|
35095
|
-
this.release = release;
|
|
35096
|
-
this.fetcher = fetcher;
|
|
35097
|
-
state.db.exec("CREATE TABLE IF NOT EXISTS cli_analytics_identity (id INTEGER PRIMARY KEY CHECK(id=1), json TEXT NOT NULL, refreshed_at INTEGER NOT NULL)");
|
|
35098
|
-
state.db.exec("CREATE TABLE IF NOT EXISTS cli_analytics_queue (id TEXT PRIMARY KEY, account_id TEXT NOT NULL, event TEXT NOT NULL, properties_json TEXT NOT NULL, occurred_at TEXT NOT NULL, attempts INTEGER NOT NULL DEFAULT 0, next_attempt_at INTEGER NOT NULL DEFAULT 0)");
|
|
35099
|
-
state.db.exec("CREATE TABLE IF NOT EXISTS cli_onboarding_attempt (id INTEGER PRIMARY KEY CHECK(id=1), attempt_id TEXT NOT NULL, account_id TEXT NOT NULL)");
|
|
35148
|
+
LINE_SEPARATOR_REGEX = /\r?\n/;
|
|
35149
|
+
defaultOptions = {
|
|
35150
|
+
timeout: void 0,
|
|
35151
|
+
persist: false
|
|
35152
|
+
};
|
|
35153
|
+
defaultSyncOptions = { timeout: void 0 };
|
|
35154
|
+
defaultNodeOptions = { windowsHide: true };
|
|
35155
|
+
ExecProcess = class {
|
|
35156
|
+
_process;
|
|
35157
|
+
_aborted = false;
|
|
35158
|
+
_options;
|
|
35159
|
+
_command;
|
|
35160
|
+
_args;
|
|
35161
|
+
_resolveClose;
|
|
35162
|
+
_processClosed;
|
|
35163
|
+
_thrownError;
|
|
35164
|
+
get process() {
|
|
35165
|
+
return this._process;
|
|
35100
35166
|
}
|
|
35101
|
-
|
|
35102
|
-
|
|
35103
|
-
if (!installation) return;
|
|
35104
|
-
this.state.db.prepare("INSERT INTO cli_onboarding_attempt (id,attempt_id,account_id) VALUES (1,?,?) ON CONFLICT(id) DO UPDATE SET attempt_id=excluded.attempt_id,account_id=excluded.account_id").run(attemptId, installation.accountId);
|
|
35167
|
+
get pid() {
|
|
35168
|
+
return this._process?.pid;
|
|
35105
35169
|
}
|
|
35106
|
-
|
|
35107
|
-
|
|
35108
|
-
if (!installation) return null;
|
|
35109
|
-
const row = this.state.db.prepare("SELECT attempt_id FROM cli_onboarding_attempt WHERE id=1 AND account_id=?").get(installation.accountId);
|
|
35110
|
-
return row?.attempt_id ?? null;
|
|
35170
|
+
get exitCode() {
|
|
35171
|
+
if (this._process && this._process.exitCode !== null) return this._process.exitCode;
|
|
35111
35172
|
}
|
|
35112
|
-
|
|
35113
|
-
|
|
35114
|
-
if (!row) return null;
|
|
35115
|
-
try {
|
|
35116
|
-
const identity2 = JSON.parse(row.json);
|
|
35117
|
-
const installation = this.state.installation();
|
|
35118
|
-
return installation && identity2.expiresAt > Date.now() && identity2.accountId === installation.accountId && identity2.workspaceId === installation.workspaceId && identity2.installationId === installation.id ? identity2 : null;
|
|
35119
|
-
} catch {
|
|
35120
|
-
return null;
|
|
35121
|
-
}
|
|
35173
|
+
get signalCode() {
|
|
35174
|
+
return this._process?.signalCode ?? null;
|
|
35122
35175
|
}
|
|
35123
|
-
|
|
35124
|
-
|
|
35125
|
-
|
|
35126
|
-
|
|
35127
|
-
|
|
35128
|
-
this.
|
|
35176
|
+
constructor(command6, args, options2) {
|
|
35177
|
+
this._options = {
|
|
35178
|
+
...defaultOptions,
|
|
35179
|
+
...options2
|
|
35180
|
+
};
|
|
35181
|
+
this._command = command6;
|
|
35182
|
+
this._args = args ?? [];
|
|
35183
|
+
this._processClosed = new Promise((resolve6) => {
|
|
35184
|
+
this._resolveClose = resolve6;
|
|
35185
|
+
});
|
|
35129
35186
|
}
|
|
35130
|
-
|
|
35131
|
-
|
|
35132
|
-
|
|
35133
|
-
|
|
35134
|
-
|
|
35135
|
-
|
|
35136
|
-
|
|
35137
|
-
|
|
35138
|
-
|
|
35139
|
-
|
|
35140
|
-
|
|
35141
|
-
|
|
35142
|
-
|
|
35143
|
-
|
|
35144
|
-
|
|
35187
|
+
kill(signal) {
|
|
35188
|
+
return this._process?.kill(signal) === true;
|
|
35189
|
+
}
|
|
35190
|
+
get aborted() {
|
|
35191
|
+
return this._aborted;
|
|
35192
|
+
}
|
|
35193
|
+
get killed() {
|
|
35194
|
+
return this._process?.killed === true;
|
|
35195
|
+
}
|
|
35196
|
+
pipe(command6, args, options2) {
|
|
35197
|
+
return exec(command6, args, {
|
|
35198
|
+
...options2,
|
|
35199
|
+
stdin: this
|
|
35200
|
+
});
|
|
35201
|
+
}
|
|
35202
|
+
async *[Symbol.asyncIterator]() {
|
|
35203
|
+
const proc = this._process;
|
|
35204
|
+
if (!proc) return;
|
|
35205
|
+
const streams = [];
|
|
35206
|
+
if (this._streamErr) streams.push(this._streamErr);
|
|
35207
|
+
if (this._streamOut) streams.push(this._streamOut);
|
|
35208
|
+
const streamCombined = combineStreams(streams);
|
|
35209
|
+
const rl = readline.createInterface({ input: streamCombined });
|
|
35210
|
+
for await (const chunk of rl) yield chunk.toString();
|
|
35211
|
+
await this._processClosed;
|
|
35212
|
+
proc.removeAllListeners();
|
|
35213
|
+
if (this._thrownError) throw this._thrownError;
|
|
35214
|
+
if (this._options?.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, void 0, this._command, this._args);
|
|
35215
|
+
}
|
|
35216
|
+
async _waitForOutput() {
|
|
35217
|
+
const proc = this._process;
|
|
35218
|
+
if (!proc) throw new Error("No process was started");
|
|
35219
|
+
const [stdout, stderr] = await Promise.all([this._streamOut ? readStream(this._streamOut) : "", this._streamErr ? readStream(this._streamErr) : ""]);
|
|
35220
|
+
await this._processClosed;
|
|
35221
|
+
const { stdin } = this._options;
|
|
35222
|
+
if (stdin && typeof stdin !== "string") await stdin;
|
|
35223
|
+
proc.removeAllListeners();
|
|
35224
|
+
if (this._thrownError) throw this._thrownError;
|
|
35225
|
+
const result3 = {
|
|
35226
|
+
stderr,
|
|
35227
|
+
stdout,
|
|
35228
|
+
exitCode: this.exitCode
|
|
35229
|
+
};
|
|
35230
|
+
if (this._options.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, result3, this._command, this._args);
|
|
35231
|
+
return result3;
|
|
35145
35232
|
}
|
|
35146
|
-
|
|
35147
|
-
|
|
35148
|
-
const installation = this.state.installation();
|
|
35149
|
-
if (!installation) return;
|
|
35150
|
-
const identity2 = this.identity();
|
|
35151
|
-
if (identity2 && !identity2.enabled) return;
|
|
35152
|
-
this.state.db.prepare("INSERT INTO cli_analytics_queue (id,account_id,event,properties_json,occurred_at) VALUES (?,?,?,?,?)").run(randomUUID10(), installation.accountId, event, JSON.stringify(scrubEventProperties(event, values)), (/* @__PURE__ */ new Date()).toISOString());
|
|
35153
|
-
this.state.db.exec("DELETE FROM cli_analytics_queue WHERE id IN (SELECT id FROM cli_analytics_queue ORDER BY occurred_at DESC LIMIT -1 OFFSET 1000)");
|
|
35233
|
+
then(onfulfilled, onrejected) {
|
|
35234
|
+
return this._waitForOutput().then(onfulfilled, onrejected);
|
|
35154
35235
|
}
|
|
35155
|
-
|
|
35156
|
-
|
|
35157
|
-
|
|
35158
|
-
const
|
|
35159
|
-
|
|
35160
|
-
|
|
35161
|
-
|
|
35162
|
-
|
|
35163
|
-
|
|
35164
|
-
|
|
35165
|
-
|
|
35166
|
-
|
|
35167
|
-
|
|
35168
|
-
|
|
35236
|
+
_streamOut;
|
|
35237
|
+
_streamErr;
|
|
35238
|
+
spawn() {
|
|
35239
|
+
const options2 = this._options;
|
|
35240
|
+
const nodeOptions = {
|
|
35241
|
+
...defaultNodeOptions,
|
|
35242
|
+
...options2.nodeOptions
|
|
35243
|
+
};
|
|
35244
|
+
const cwd$1 = nodeOptions?.cwd ?? cwd();
|
|
35245
|
+
const signals = [];
|
|
35246
|
+
this._resetState();
|
|
35247
|
+
if (options2.timeout !== void 0) signals.push(AbortSignal.timeout(options2.timeout));
|
|
35248
|
+
if (options2.signal !== void 0) signals.push(options2.signal);
|
|
35249
|
+
if (options2.persist === true) nodeOptions.detached = true;
|
|
35250
|
+
if (signals.length > 0) nodeOptions.signal = combineSignals(signals);
|
|
35251
|
+
nodeOptions.env = computeEnv(cwd$1, nodeOptions.env, options2.nodePath);
|
|
35252
|
+
const crossResult = normalizeSpawnCommand(this._command, this._args, nodeOptions);
|
|
35253
|
+
const handle2 = spawn2(crossResult.command, crossResult.args, crossResult.options);
|
|
35254
|
+
if (handle2.stderr) this._streamErr = handle2.stderr;
|
|
35255
|
+
if (handle2.stdout) this._streamOut = handle2.stdout;
|
|
35256
|
+
this._process = handle2;
|
|
35257
|
+
handle2.once("error", this._onError);
|
|
35258
|
+
handle2.once("close", this._onClose);
|
|
35259
|
+
if (handle2.stdin) {
|
|
35260
|
+
const { stdin } = options2;
|
|
35261
|
+
if (typeof stdin === "string") handle2.stdin.end(stdin);
|
|
35262
|
+
else stdin?.process?.stdout?.pipe(handle2.stdin);
|
|
35169
35263
|
}
|
|
35170
35264
|
}
|
|
35265
|
+
_resetState() {
|
|
35266
|
+
this._aborted = false;
|
|
35267
|
+
this._processClosed = new Promise((resolve6) => {
|
|
35268
|
+
this._resolveClose = resolve6;
|
|
35269
|
+
});
|
|
35270
|
+
this._thrownError = void 0;
|
|
35271
|
+
}
|
|
35272
|
+
_onError = (err) => {
|
|
35273
|
+
if (err.name === "AbortError" && (!(err.cause instanceof Error) || err.cause.name !== "TimeoutError")) {
|
|
35274
|
+
this._aborted = true;
|
|
35275
|
+
return;
|
|
35276
|
+
}
|
|
35277
|
+
this._thrownError = err;
|
|
35278
|
+
};
|
|
35279
|
+
_onClose = () => {
|
|
35280
|
+
if (this._resolveClose) this._resolveClose();
|
|
35281
|
+
};
|
|
35282
|
+
};
|
|
35283
|
+
x = (command6, args, userOptions) => {
|
|
35284
|
+
const proc = new ExecProcess(command6, args, userOptions);
|
|
35285
|
+
proc.spawn();
|
|
35286
|
+
return proc;
|
|
35171
35287
|
};
|
|
35288
|
+
exec = x;
|
|
35172
35289
|
}
|
|
35173
35290
|
});
|
|
35174
35291
|
|
|
35175
|
-
// src/
|
|
35176
|
-
import {
|
|
35177
|
-
import { existsSync as
|
|
35292
|
+
// src/plugin.ts
|
|
35293
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
35294
|
+
import { cpSync, existsSync as existsSync4, mkdirSync as mkdirSync9, readFileSync as readFileSync9, readdirSync, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
|
|
35295
|
+
import { homedir as homedir2 } from "node:os";
|
|
35296
|
+
import { dirname as dirname7, join as join13, resolve as resolve3 } from "node:path";
|
|
35178
35297
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
35179
|
-
function
|
|
35180
|
-
|
|
35181
|
-
|
|
35182
|
-
|
|
35298
|
+
function missingSkill(root) {
|
|
35299
|
+
return skillNames.find((name) => !existsSync4(join13(root, "skills", name, "SKILL.md")));
|
|
35300
|
+
}
|
|
35301
|
+
function completeCopy(source, target) {
|
|
35302
|
+
return files(source).every((path2) => existsSync4(join13(target, path2)));
|
|
35303
|
+
}
|
|
35304
|
+
function files(root, relative = "") {
|
|
35305
|
+
return readdirSync(join13(root, relative), { withFileTypes: true }).flatMap((entry2) => {
|
|
35306
|
+
const path2 = join13(relative, entry2.name);
|
|
35307
|
+
return entry2.isDirectory() ? files(root, path2) : [path2];
|
|
35308
|
+
}).sort();
|
|
35309
|
+
}
|
|
35310
|
+
function digest(root) {
|
|
35311
|
+
const hash4 = createHash5("sha256");
|
|
35312
|
+
for (const path2 of files(root)) hash4.update(path2).update("\0").update(readFileSync9(join13(root, path2))).update("\0");
|
|
35313
|
+
return hash4.digest("hex");
|
|
35314
|
+
}
|
|
35315
|
+
function writeJson(path2, value) {
|
|
35316
|
+
mkdirSync9(dirname7(path2), { recursive: true });
|
|
35317
|
+
writeFileSync8(path2, `${JSON.stringify(value, null, 2)}
|
|
35318
|
+
`, { mode: 384 });
|
|
35319
|
+
}
|
|
35320
|
+
function readJson(path2) {
|
|
35183
35321
|
try {
|
|
35184
|
-
|
|
35322
|
+
return JSON.parse(readFileSync9(path2, "utf8"));
|
|
35185
35323
|
} catch {
|
|
35324
|
+
return null;
|
|
35186
35325
|
}
|
|
35187
35326
|
}
|
|
35188
|
-
|
|
35189
|
-
"
|
|
35190
|
-
|
|
35191
|
-
|
|
35192
|
-
}
|
|
35193
|
-
|
|
35194
|
-
// ../../node_modules/.pnpm/tinyexec@1.3.1/node_modules/tinyexec/dist/main.mjs
|
|
35195
|
-
import { spawn as spawn3, spawnSync } from "node:child_process";
|
|
35196
|
-
import { cwd } from "node:process";
|
|
35197
|
-
import { basename, delimiter, dirname as dirname7, normalize, resolve as resolve3 } from "node:path";
|
|
35198
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35199
|
-
import { pipeline } from "node:stream/promises";
|
|
35200
|
-
import { PassThrough } from "node:stream";
|
|
35201
|
-
import readline from "node:readline";
|
|
35202
|
-
import { closeSync, openSync, readSync, statSync } from "node:fs";
|
|
35203
|
-
function getPathFromEnv(env) {
|
|
35204
|
-
for (const key in env) {
|
|
35205
|
-
if (!Object.prototype.hasOwnProperty.call(env, key) || !isPathLikePattern.test(key)) continue;
|
|
35206
|
-
const value = env[key];
|
|
35207
|
-
if (!value) return defaultEnvPathInfo;
|
|
35208
|
-
return {
|
|
35209
|
-
key,
|
|
35210
|
-
value
|
|
35211
|
-
};
|
|
35327
|
+
function command5(binary, args) {
|
|
35328
|
+
const { stdout: output2 } = xSync(binary, args, { timeout: 1e4, throwOnError: true, nodeOptions: { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] } });
|
|
35329
|
+
try {
|
|
35330
|
+
return JSON.parse(output2);
|
|
35331
|
+
} catch {
|
|
35332
|
+
return output2;
|
|
35212
35333
|
}
|
|
35213
|
-
return defaultEnvPathInfo;
|
|
35214
35334
|
}
|
|
35215
|
-
function
|
|
35216
|
-
const
|
|
35217
|
-
|
|
35218
|
-
|
|
35219
|
-
|
|
35220
|
-
|
|
35221
|
-
|
|
35222
|
-
|
|
35223
|
-
|
|
35224
|
-
|
|
35225
|
-
|
|
35226
|
-
|
|
35227
|
-
|
|
35228
|
-
|
|
35229
|
-
|
|
35230
|
-
|
|
35335
|
+
function active(agent2, expected) {
|
|
35336
|
+
const args = agent2 === "codex" ? ["plugin", "list", "--marketplace", "personal", "--json"] : ["plugin", "list", "--json"];
|
|
35337
|
+
try {
|
|
35338
|
+
const listed = command5(agent2, args);
|
|
35339
|
+
const entries = agent2 === "codex" ? listed?.installed : listed;
|
|
35340
|
+
if (!Array.isArray(entries) || entries.some((entry2) => typeof entry2 !== "object" || entry2 === null || typeof (agent2 === "codex" ? entry2.pluginId : entry2.id) !== "string")) return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: plugin list returned an unexpected response` };
|
|
35341
|
+
const plugin = entries.find((entry2) => (agent2 === "codex" ? entry2.pluginId : entry2.id) === "apilift@personal");
|
|
35342
|
+
if (!plugin) return { ready: false, known: true, detail: "Apilift is not installed in this agent" };
|
|
35343
|
+
if (typeof plugin.enabled !== "boolean" || typeof plugin.version !== "string") return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: Apilift status is incomplete` };
|
|
35344
|
+
if (!plugin.enabled) return { ready: false, known: true, detail: "Apilift is disabled in this agent" };
|
|
35345
|
+
if (plugin.version !== expected) return { ready: false, known: true, detail: "The active Apilift plugin does not match the packaged version" };
|
|
35346
|
+
return { ready: true, known: true, detail: "Apilift setup, use and discovery skills are active" };
|
|
35347
|
+
} catch (error62) {
|
|
35348
|
+
const code = typeof error62 === "object" && error62 && "code" in error62 ? error62.code : void 0;
|
|
35349
|
+
const reason = code === "ETIMEDOUT" ? "plugin list timed out after 10 seconds" : code === "ENOENT" ? `${agent2} executable was not found` : "plugin list failed";
|
|
35350
|
+
return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: ${reason}` };
|
|
35351
|
+
}
|
|
35231
35352
|
}
|
|
35232
|
-
function
|
|
35233
|
-
|
|
35234
|
-
|
|
35235
|
-
|
|
35236
|
-
};
|
|
35237
|
-
|
|
35238
|
-
|
|
35239
|
-
|
|
35240
|
-
|
|
35353
|
+
function inspectAgentPlugin(agent2, env, sourceOverride) {
|
|
35354
|
+
if (env.APILIFT_DEV_PLUGIN_ROOT) return { ready: false, version: "development", detail: "Development plugin activation has not been verified" };
|
|
35355
|
+
const source = resolve3(sourceOverride || join13(dirname7(fileURLToPath2(import.meta.url)), "plugin"));
|
|
35356
|
+
const missing = missingSkill(source);
|
|
35357
|
+
if (missing) return { ready: false, version: "unknown", detail: `CLI package is missing its ${missing} skill` };
|
|
35358
|
+
const version2 = readJson(join13(source, `.${agent2}-plugin`, "plugin.json"))?.version;
|
|
35359
|
+
if (typeof version2 !== "string" || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(version2)) throw new Error("Plugin package version is invalid");
|
|
35360
|
+
const bundleDigest = digest(source);
|
|
35361
|
+
const expected = agent2 === "codex" ? `${version2}+codex.${bundleDigest.slice(0, 12)}` : version2;
|
|
35362
|
+
const home = resolve3(env.APILIFT_AGENT_HOME || homedir2());
|
|
35363
|
+
const plugin = agent2 === "codex" ? join13(home, "plugins", "apilift") : join13(home, ".agents", "plugins", "plugins", "apilift");
|
|
35364
|
+
const marker = readJson(join13(plugin, markerName));
|
|
35365
|
+
const staged = marker?.package === "apilift" && marker.bundleDigest === bundleDigest && marker.version === version2 && completeCopy(source, plugin);
|
|
35366
|
+
if (!staged) return { ready: false, version: expected, detail: "Apilift plugin files are missing or stale" };
|
|
35367
|
+
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: "Apilift skills are staged; activation is unverified" };
|
|
35368
|
+
const activation = active(agent2, expected);
|
|
35369
|
+
return { ready: activation.ready, version: expected, detail: activation.detail, checkFailed: !activation.known };
|
|
35241
35370
|
}
|
|
35242
|
-
function
|
|
35243
|
-
if (
|
|
35244
|
-
|
|
35245
|
-
|
|
35246
|
-
|
|
35247
|
-
|
|
35248
|
-
|
|
35249
|
-
|
|
35250
|
-
|
|
35251
|
-
const size = 150;
|
|
35252
|
-
const buffer = Buffer.alloc(size);
|
|
35253
|
-
let fd = null;
|
|
35254
|
-
try {
|
|
35255
|
-
fd = openSync(file2, "r");
|
|
35256
|
-
readSync(fd, buffer, 0, size, 0);
|
|
35257
|
-
} catch {
|
|
35258
|
-
} finally {
|
|
35259
|
-
if (fd !== null) closeSync(fd);
|
|
35260
|
-
}
|
|
35261
|
-
const match = buffer.toString().match(shebangRegExp);
|
|
35262
|
-
if (match !== null) {
|
|
35263
|
-
const line = match[1].trim();
|
|
35264
|
-
const separatorIndex = line.indexOf(" ");
|
|
35265
|
-
const path2 = separatorIndex !== -1 ? line.slice(0, separatorIndex) : line;
|
|
35266
|
-
const argument = separatorIndex !== -1 ? line.slice(separatorIndex + 1) : "";
|
|
35267
|
-
const binary = basename(path2);
|
|
35268
|
-
shebang = binary === "env" ? argument || null : binary;
|
|
35269
|
-
}
|
|
35270
|
-
}
|
|
35271
|
-
if (shebang !== null && file2 !== null) {
|
|
35272
|
-
args = [file2, ...args];
|
|
35273
|
-
command6 = shebang;
|
|
35274
|
-
file2 = resolveCommand(command6, options2);
|
|
35371
|
+
function ensureAgentPlugin(agent2, env, sourceOverride) {
|
|
35372
|
+
if (env.APILIFT_DEV_PLUGIN_ROOT) {
|
|
35373
|
+
const source2 = resolve3(env.APILIFT_DEV_PLUGIN_ROOT);
|
|
35374
|
+
const missing2 = missingSkill(source2);
|
|
35375
|
+
if (missing2) throw new Error(`Development plugin ${missing2} skill is missing`);
|
|
35376
|
+
const bundleDigest2 = digest(source2);
|
|
35377
|
+
const root = resolve3(env.APILIFT_HOME || join13(homedir2(), ".local", "share", "apilift"));
|
|
35378
|
+
writeJson(join13(root, "agent-plugins", `${agent2}.json`), { root: source2, digest: bundleDigest2 });
|
|
35379
|
+
return { ready: false, version: `dev+${bundleDigest2.slice(0, 12)}`, detail: "Development plugin source recorded; activation was not verified" };
|
|
35275
35380
|
}
|
|
35276
|
-
|
|
35277
|
-
|
|
35278
|
-
|
|
35279
|
-
|
|
35280
|
-
|
|
35281
|
-
|
|
35282
|
-
|
|
35283
|
-
|
|
35284
|
-
|
|
35285
|
-
|
|
35286
|
-
|
|
35287
|
-
|
|
35288
|
-
|
|
35289
|
-
|
|
35290
|
-
|
|
35291
|
-
|
|
35292
|
-
|
|
35293
|
-
|
|
35294
|
-
|
|
35295
|
-
|
|
35296
|
-
|
|
35297
|
-
|
|
35298
|
-
|
|
35381
|
+
const source = resolve3(sourceOverride || join13(dirname7(fileURLToPath2(import.meta.url)), "plugin"));
|
|
35382
|
+
const missing = missingSkill(source);
|
|
35383
|
+
if (missing) throw new Error(`CLI package is missing its ${missing} skill`);
|
|
35384
|
+
const version2 = readJson(join13(source, `.${agent2}-plugin`, "plugin.json"))?.version;
|
|
35385
|
+
if (typeof version2 !== "string" || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(version2)) throw new Error("Plugin package version is invalid");
|
|
35386
|
+
const bundleDigest = digest(source);
|
|
35387
|
+
const home = resolve3(env.APILIFT_AGENT_HOME || homedir2());
|
|
35388
|
+
const marketplace = join13(home, ".agents", "plugins");
|
|
35389
|
+
const plugin = agent2 === "codex" ? join13(home, "plugins", "apilift") : join13(marketplace, "plugins", "apilift");
|
|
35390
|
+
const marker = readJson(join13(plugin, markerName));
|
|
35391
|
+
if (existsSync4(plugin) && marker?.package !== "apilift") throw new Error(`Refusing to replace unmanaged plugin ${plugin}`);
|
|
35392
|
+
const expected = agent2 === "codex" ? `${version2}+codex.${bundleDigest.slice(0, 12)}` : version2;
|
|
35393
|
+
const current = marker?.bundleDigest === bundleDigest && marker.version === version2 && completeCopy(source, plugin);
|
|
35394
|
+
if (!current) {
|
|
35395
|
+
const staging = `${plugin}.stage-${process.pid}`;
|
|
35396
|
+
rmSync4(staging, { recursive: true, force: true });
|
|
35397
|
+
mkdirSync9(dirname7(staging), { recursive: true });
|
|
35398
|
+
cpSync(source, staging, { recursive: true });
|
|
35399
|
+
const manifestPath = join13(staging, `.${agent2}-plugin`, "plugin.json");
|
|
35400
|
+
const manifest = readJson(manifestPath);
|
|
35401
|
+
if (!manifest) throw new Error("Plugin manifest is invalid");
|
|
35402
|
+
manifest.version = expected;
|
|
35403
|
+
writeJson(manifestPath, manifest);
|
|
35404
|
+
writeJson(join13(staging, markerName), { schema: "apilift.plugin-install/v1", package: "apilift", version: version2, bundleDigest });
|
|
35405
|
+
const backup = `${plugin}.backup-${process.pid}`;
|
|
35406
|
+
if (existsSync4(plugin)) renameSync3(plugin, backup);
|
|
35407
|
+
try {
|
|
35408
|
+
renameSync3(staging, plugin);
|
|
35409
|
+
} catch (error62) {
|
|
35410
|
+
if (existsSync4(backup)) renameSync3(backup, plugin);
|
|
35411
|
+
throw error62;
|
|
35412
|
+
}
|
|
35413
|
+
rmSync4(backup, { recursive: true, force: true });
|
|
35299
35414
|
}
|
|
35300
|
-
|
|
35301
|
-
|
|
35302
|
-
|
|
35303
|
-
|
|
35304
|
-
|
|
35305
|
-
}
|
|
35306
|
-
|
|
35307
|
-
const
|
|
35308
|
-
|
|
35309
|
-
|
|
35310
|
-
|
|
35311
|
-
|
|
35312
|
-
|
|
35313
|
-
|
|
35314
|
-
const unquoted = path2.startsWith('"') && path2.endsWith('"') && path2.length > 1 ? path2.slice(1, -1) : path2;
|
|
35315
|
-
const dest = resolve3(cwd$3, unquoted, command6);
|
|
35316
|
-
for (const ext of extensions) {
|
|
35317
|
-
const destWithExt = dest + ext;
|
|
35415
|
+
const marketplacePath = join13(marketplace, "marketplace.json");
|
|
35416
|
+
const document = readJson(marketplacePath) ?? { name: "personal", interface: { displayName: "Personal" }, plugins: [] };
|
|
35417
|
+
if (document.name !== "personal" || !Array.isArray(document.plugins)) throw new Error("Unsupported personal plugin marketplace");
|
|
35418
|
+
document.plugins = [...document.plugins.filter((item) => typeof item === "object" && item !== null && item.name !== "apilift"), { name: "apilift", source: { source: "local", path: "./plugins/apilift" }, policy: { installation: "AVAILABLE", authentication: "ON_INSTALL" }, category: "Developer Tools" }];
|
|
35419
|
+
writeJson(marketplacePath, document);
|
|
35420
|
+
writeJson(join13(marketplace, ".claude-plugin", "marketplace.json"), { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name: "personal", description: "Personal agent plugins", owner: { name: "Local" }, plugins: [{ name: "apilift", description: "Use logged-in apps and discover missing actions with Apilift", source: "./plugins/apilift", category: "development" }] });
|
|
35421
|
+
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: `Plugin staged at ${plugin}; activation is disabled` };
|
|
35422
|
+
const initial = active(agent2, expected);
|
|
35423
|
+
if (!initial.known) return { ready: false, version: expected, detail: initial.detail, checkFailed: true };
|
|
35424
|
+
if (initial.ready) return { ready: true, version: expected, detail: initial.detail };
|
|
35425
|
+
{
|
|
35426
|
+
if (agent2 === "codex") command5("codex", ["plugin", "add", "apilift@personal"]);
|
|
35427
|
+
else {
|
|
35428
|
+
let marketplaces;
|
|
35318
35429
|
try {
|
|
35319
|
-
|
|
35430
|
+
marketplaces = command5("claude", ["plugin", "marketplace", "list", "--json"]);
|
|
35320
35431
|
} catch {
|
|
35432
|
+
marketplaces = [];
|
|
35321
35433
|
}
|
|
35434
|
+
if (!Array.isArray(marketplaces) || !marketplaces.some((item) => typeof item === "object" && item !== null && item.name === "personal")) command5("claude", ["plugin", "marketplace", "add", marketplace, "--scope", "user"]);
|
|
35435
|
+
const listed = command5("claude", ["plugin", "list", "--json"]);
|
|
35436
|
+
const installed = Array.isArray(listed) && listed.some((item) => typeof item === "object" && item !== null && item.id === "apilift@personal");
|
|
35437
|
+
command5("claude", ["plugin", installed ? "update" : "install", "apilift@personal", "--scope", "user"]);
|
|
35438
|
+
command5("claude", ["plugin", "enable", "apilift@personal", "--scope", "user"]);
|
|
35322
35439
|
}
|
|
35323
35440
|
}
|
|
35324
|
-
|
|
35441
|
+
const activation = active(agent2, expected);
|
|
35442
|
+
return { ready: activation.ready, version: expected, detail: activation.detail, checkFailed: !activation.known };
|
|
35325
35443
|
}
|
|
35326
|
-
|
|
35327
|
-
|
|
35328
|
-
|
|
35329
|
-
|
|
35330
|
-
|
|
35331
|
-
|
|
35332
|
-
|
|
35333
|
-
const onAbort = () => {
|
|
35334
|
-
controller.abort(signal.reason);
|
|
35335
|
-
};
|
|
35336
|
-
signal.addEventListener("abort", onAbort, { signal: controller.signal });
|
|
35444
|
+
var markerName, skillNames;
|
|
35445
|
+
var init_plugin = __esm({
|
|
35446
|
+
"src/plugin.ts"() {
|
|
35447
|
+
"use strict";
|
|
35448
|
+
init_main2();
|
|
35449
|
+
markerName = ".apilift-managed.json";
|
|
35450
|
+
skillNames = ["setup", "use", "discover"];
|
|
35337
35451
|
}
|
|
35338
|
-
|
|
35339
|
-
|
|
35340
|
-
|
|
35341
|
-
|
|
35452
|
+
});
|
|
35453
|
+
|
|
35454
|
+
// ../../packages/core/dist/analytics/index.js
|
|
35455
|
+
function normalizeRoute(route) {
|
|
35342
35456
|
try {
|
|
35343
|
-
|
|
35457
|
+
const parsed = new URL(route, "https://apilift.dev");
|
|
35458
|
+
return parsed.pathname.replace(/^\/dashboard\/apps\/[^/]+/, "/dashboard/apps/:app").replace(uuid5, ":id").replace(longId, ":id");
|
|
35344
35459
|
} catch {
|
|
35460
|
+
return "/invalid";
|
|
35345
35461
|
}
|
|
35346
|
-
return output2;
|
|
35347
35462
|
}
|
|
35348
|
-
|
|
35349
|
-
|
|
35350
|
-
|
|
35351
|
-
|
|
35352
|
-
|
|
35353
|
-
|
|
35354
|
-
|
|
35355
|
-
|
|
35356
|
-
|
|
35357
|
-
|
|
35358
|
-
|
|
35359
|
-
|
|
35360
|
-
|
|
35361
|
-
|
|
35362
|
-
|
|
35363
|
-
|
|
35364
|
-
|
|
35365
|
-
|
|
35366
|
-
|
|
35367
|
-
|
|
35368
|
-
|
|
35369
|
-
|
|
35370
|
-
|
|
35371
|
-
"
|
|
35372
|
-
"
|
|
35373
|
-
"
|
|
35374
|
-
"
|
|
35375
|
-
|
|
35376
|
-
|
|
35377
|
-
|
|
35378
|
-
|
|
35379
|
-
|
|
35380
|
-
|
|
35381
|
-
|
|
35382
|
-
|
|
35383
|
-
|
|
35384
|
-
|
|
35385
|
-
|
|
35386
|
-
|
|
35387
|
-
|
|
35388
|
-
|
|
35389
|
-
|
|
35390
|
-
|
|
35391
|
-
|
|
35392
|
-
|
|
35393
|
-
|
|
35394
|
-
|
|
35395
|
-
|
|
35396
|
-
|
|
35397
|
-
|
|
35398
|
-
|
|
35399
|
-
|
|
35400
|
-
|
|
35401
|
-
|
|
35402
|
-
|
|
35403
|
-
|
|
35404
|
-
|
|
35405
|
-
|
|
35406
|
-
|
|
35407
|
-
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
|
|
35416
|
-
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35421
|
-
|
|
35422
|
-
|
|
35423
|
-
|
|
35424
|
-
|
|
35425
|
-
|
|
35426
|
-
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
|
|
35432
|
-
|
|
35433
|
-
|
|
35434
|
-
|
|
35435
|
-
|
|
35436
|
-
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
|
|
35442
|
-
|
|
35443
|
-
|
|
35463
|
+
function scrubEventProperties(event, input2) {
|
|
35464
|
+
const allowed = eventProperties[event];
|
|
35465
|
+
const result3 = {};
|
|
35466
|
+
for (const [key, value] of Object.entries(input2)) {
|
|
35467
|
+
if (!allowed.includes(key))
|
|
35468
|
+
continue;
|
|
35469
|
+
const normalized = key === "route" && typeof value === "string" ? normalizeRoute(value) : value;
|
|
35470
|
+
if (typeof normalized === "boolean" || typeof normalized === "number" && Number.isFinite(normalized) || typeof normalized === "string" && safeString.test(normalized))
|
|
35471
|
+
result3[key] = normalized;
|
|
35472
|
+
}
|
|
35473
|
+
return result3;
|
|
35474
|
+
}
|
|
35475
|
+
var eventProperties, safeString, uuid5, longId;
|
|
35476
|
+
var init_analytics = __esm({
|
|
35477
|
+
"../../packages/core/dist/analytics/index.js"() {
|
|
35478
|
+
"use strict";
|
|
35479
|
+
eventProperties = {
|
|
35480
|
+
"$pageview": ["route"],
|
|
35481
|
+
navigation_clicked: ["route", "target"],
|
|
35482
|
+
pricing_viewed: ["route"],
|
|
35483
|
+
catalog_viewed: ["route"],
|
|
35484
|
+
app_page_viewed: ["route"],
|
|
35485
|
+
onboarding_entered: ["route"],
|
|
35486
|
+
broken_page_viewed: ["route"],
|
|
35487
|
+
authentication_started: ["source", "stage"],
|
|
35488
|
+
authentication_code_sent: ["source", "stage"],
|
|
35489
|
+
authentication_completed: ["source", "stage"],
|
|
35490
|
+
authentication_failed: ["source", "stage", "code"],
|
|
35491
|
+
onboarding_attempt_started: ["attempt_id", "agent", "stage", "outcome", "source", "target"],
|
|
35492
|
+
onboarding_stage_viewed: ["attempt_id", "agent", "stage"],
|
|
35493
|
+
setup_prompt_copied: ["attempt_id", "agent", "stage"],
|
|
35494
|
+
onboarding_next_action_selected: ["attempt_id", "agent", "target"],
|
|
35495
|
+
onboarding_failed: ["stage", "attempt_id", "code", "outcome", "duration_ms"],
|
|
35496
|
+
checkout_requested: ["plan", "interval", "stage", "source"],
|
|
35497
|
+
checkout_ui_changed: ["plan", "interval", "stage", "source"],
|
|
35498
|
+
billing_portal_requested: ["source"],
|
|
35499
|
+
paid_feature_viewed: ["code", "route"],
|
|
35500
|
+
paid_feature_upgrade_opened: ["code", "route"],
|
|
35501
|
+
account_created: [],
|
|
35502
|
+
account_deleted: [],
|
|
35503
|
+
agent_selected: ["agent", "attempt_id", "status"],
|
|
35504
|
+
device_authorization_changed: ["agent", "attempt_id", "status"],
|
|
35505
|
+
onboarding_stage_completed: ["stage", "active", "agent"],
|
|
35506
|
+
installation_readiness_changed: ["stage", "active", "agent"],
|
|
35507
|
+
app_made_public: ["app_id"],
|
|
35508
|
+
execution_finished: ["app_id", "action_id", "outcome", "duration_ms", "http_status", "agent", "purpose"],
|
|
35509
|
+
activation_changed: ["activated"],
|
|
35510
|
+
execution_classified: ["purpose", "revision"],
|
|
35511
|
+
value_snapshot: ["saved_time_ms", "saved_tokens", "saved_value_microusd", "saved_time_ms_available", "saved_tokens_available", "saved_value_microusd_available"],
|
|
35512
|
+
trial_started: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35513
|
+
trial_progress: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35514
|
+
trial_expired: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35515
|
+
trial_completed: ["plan", "trial_day", "trial_days_remaining", "outcome"],
|
|
35516
|
+
payment_completed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35517
|
+
payment_status_changed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35518
|
+
payment_failed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35519
|
+
subscription_changed: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35520
|
+
payment_adjusted: ["plan", "interval", "status", "previous_status", "currency", "amount", "billing_environment", "synthetic"],
|
|
35521
|
+
critical_failure: ["code", "count"],
|
|
35522
|
+
cli_command_finished: ["command", "purpose", "outcome", "duration_ms", "stage", "agent"],
|
|
35523
|
+
setup_stage_changed: ["stage", "agent"],
|
|
35524
|
+
discovery_started: ["purpose", "agent"],
|
|
35525
|
+
discovery_finished: ["purpose", "outcome", "duration_ms", "agent"],
|
|
35526
|
+
client_exception: ["code"],
|
|
35527
|
+
native_host_connected: [],
|
|
35528
|
+
native_host_failure: ["code", "operation", "stage", "origin", "failure_count", "duration_ms"],
|
|
35529
|
+
native_host_recovered: ["operation", "stage", "origin", "failure_count", "duration_ms"],
|
|
35530
|
+
extension_installed: ["stage"],
|
|
35531
|
+
extension_connected: ["stage"],
|
|
35532
|
+
extension_disconnected: ["stage"],
|
|
35533
|
+
extension_failure: ["code"],
|
|
35534
|
+
extension_interaction: ["stage", "outcome"],
|
|
35535
|
+
credential_setup_finished: ["stage", "outcome", "code"],
|
|
35536
|
+
"$exception": ["route", "method", "exception_type", "exception_frames", "exception_handled", "exception_level"]
|
|
35537
|
+
};
|
|
35538
|
+
safeString = /^[a-zA-Z0-9_./:{} -]{1,160}$/;
|
|
35539
|
+
uuid5 = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi;
|
|
35540
|
+
longId = /\b[a-zA-Z0-9_-]{24,}\b/g;
|
|
35541
|
+
}
|
|
35542
|
+
});
|
|
35543
|
+
|
|
35544
|
+
// src/analytics.ts
|
|
35545
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
35546
|
+
var EVENT, EU_HOST, CliAnalytics;
|
|
35547
|
+
var init_analytics2 = __esm({
|
|
35548
|
+
"src/analytics.ts"() {
|
|
35549
|
+
"use strict";
|
|
35550
|
+
init_analytics();
|
|
35551
|
+
init_api2();
|
|
35552
|
+
init_api3();
|
|
35553
|
+
EVENT = /* @__PURE__ */ new Set(["cli_command_finished", "setup_stage_changed", "onboarding_failed", "discovery_started", "discovery_finished", "client_exception"]);
|
|
35554
|
+
EU_HOST = "https://eu.i.posthog.com";
|
|
35555
|
+
CliAnalytics = class {
|
|
35556
|
+
constructor(state, release = "1.0.0", fetcher = fetch) {
|
|
35557
|
+
this.state = state;
|
|
35558
|
+
this.release = release;
|
|
35559
|
+
this.fetcher = fetcher;
|
|
35560
|
+
state.db.exec("CREATE TABLE IF NOT EXISTS cli_analytics_identity (id INTEGER PRIMARY KEY CHECK(id=1), json TEXT NOT NULL, refreshed_at INTEGER NOT NULL)");
|
|
35561
|
+
state.db.exec("CREATE TABLE IF NOT EXISTS cli_analytics_queue (id TEXT PRIMARY KEY, account_id TEXT NOT NULL, event TEXT NOT NULL, properties_json TEXT NOT NULL, occurred_at TEXT NOT NULL, attempts INTEGER NOT NULL DEFAULT 0, next_attempt_at INTEGER NOT NULL DEFAULT 0)");
|
|
35562
|
+
state.db.exec("CREATE TABLE IF NOT EXISTS cli_onboarding_attempt (id INTEGER PRIMARY KEY CHECK(id=1), attempt_id TEXT NOT NULL, account_id TEXT NOT NULL)");
|
|
35444
35563
|
}
|
|
35445
|
-
|
|
35446
|
-
|
|
35447
|
-
|
|
35448
|
-
|
|
35449
|
-
});
|
|
35564
|
+
saveOnboardingAttempt(attemptId) {
|
|
35565
|
+
const installation = this.state.installation();
|
|
35566
|
+
if (!installation) return;
|
|
35567
|
+
this.state.db.prepare("INSERT INTO cli_onboarding_attempt (id,attempt_id,account_id) VALUES (1,?,?) ON CONFLICT(id) DO UPDATE SET attempt_id=excluded.attempt_id,account_id=excluded.account_id").run(attemptId, installation.accountId);
|
|
35450
35568
|
}
|
|
35451
|
-
|
|
35452
|
-
const
|
|
35453
|
-
if (!
|
|
35454
|
-
const
|
|
35455
|
-
|
|
35456
|
-
if (this._streamOut) streams.push(this._streamOut);
|
|
35457
|
-
const streamCombined = combineStreams(streams);
|
|
35458
|
-
const rl = readline.createInterface({ input: streamCombined });
|
|
35459
|
-
for await (const chunk of rl) yield chunk.toString();
|
|
35460
|
-
await this._processClosed;
|
|
35461
|
-
proc.removeAllListeners();
|
|
35462
|
-
if (this._thrownError) throw this._thrownError;
|
|
35463
|
-
if (this._options?.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, void 0, this._command, this._args);
|
|
35569
|
+
onboardingAttempt() {
|
|
35570
|
+
const installation = this.state.installation();
|
|
35571
|
+
if (!installation) return null;
|
|
35572
|
+
const row = this.state.db.prepare("SELECT attempt_id FROM cli_onboarding_attempt WHERE id=1 AND account_id=?").get(installation.accountId);
|
|
35573
|
+
return row?.attempt_id ?? null;
|
|
35464
35574
|
}
|
|
35465
|
-
|
|
35466
|
-
const
|
|
35467
|
-
if (!
|
|
35468
|
-
|
|
35469
|
-
|
|
35470
|
-
|
|
35471
|
-
|
|
35472
|
-
|
|
35473
|
-
|
|
35474
|
-
|
|
35475
|
-
stderr,
|
|
35476
|
-
stdout,
|
|
35477
|
-
exitCode: this.exitCode
|
|
35478
|
-
};
|
|
35479
|
-
if (this._options.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, result3, this._command, this._args);
|
|
35480
|
-
return result3;
|
|
35575
|
+
identity() {
|
|
35576
|
+
const row = this.state.db.prepare("SELECT json FROM cli_analytics_identity WHERE id=1").get();
|
|
35577
|
+
if (!row) return null;
|
|
35578
|
+
try {
|
|
35579
|
+
const identity2 = JSON.parse(row.json);
|
|
35580
|
+
const installation = this.state.installation();
|
|
35581
|
+
return installation && identity2.expiresAt > Date.now() && identity2.accountId === installation.accountId && identity2.workspaceId === installation.workspaceId && identity2.installationId === installation.id ? identity2 : null;
|
|
35582
|
+
} catch {
|
|
35583
|
+
return null;
|
|
35584
|
+
}
|
|
35481
35585
|
}
|
|
35482
|
-
|
|
35483
|
-
|
|
35586
|
+
updateIdentity(me2, now = Date.now()) {
|
|
35587
|
+
const previous = this.identity();
|
|
35588
|
+
const next = { accountId: me2.account.id, workspaceId: me2.workspace.id, installationId: me2.installation.id, ...me2.analytics, enabled: me2.analytics.enabled && me2.analytics.environment !== "disabled" && me2.analytics.host === EU_HOST && /^phc_[A-Za-z0-9]+$/u.test(me2.analytics.projectKey), expiresAt: now + 24 * 60 * 6e4 };
|
|
35589
|
+
if (!next.enabled || previous && previous.accountId !== next.accountId) this.state.db.exec("DELETE FROM cli_analytics_queue");
|
|
35590
|
+
this.state.db.prepare("INSERT INTO cli_analytics_identity (id,json,refreshed_at) VALUES (1,?,?) ON CONFLICT(id) DO UPDATE SET json=excluded.json,refreshed_at=excluded.refreshed_at").run(JSON.stringify(next), now);
|
|
35591
|
+
this.state.db.prepare("DELETE FROM cli_analytics_queue WHERE account_id<>? OR occurred_at<?").run(next.accountId, new Date(now - 7 * 864e5).toISOString());
|
|
35484
35592
|
}
|
|
35485
|
-
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
const
|
|
35489
|
-
|
|
35490
|
-
|
|
35491
|
-
|
|
35492
|
-
|
|
35493
|
-
|
|
35494
|
-
|
|
35495
|
-
|
|
35496
|
-
|
|
35497
|
-
|
|
35498
|
-
|
|
35499
|
-
if (signals.length > 0) nodeOptions.signal = combineSignals(signals);
|
|
35500
|
-
nodeOptions.env = computeEnv(cwd$1, nodeOptions.env, options2.nodePath);
|
|
35501
|
-
const crossResult = normalizeSpawnCommand(this._command, this._args, nodeOptions);
|
|
35502
|
-
const handle2 = spawn3(crossResult.command, crossResult.args, crossResult.options);
|
|
35503
|
-
if (handle2.stderr) this._streamErr = handle2.stderr;
|
|
35504
|
-
if (handle2.stdout) this._streamOut = handle2.stdout;
|
|
35505
|
-
this._process = handle2;
|
|
35506
|
-
handle2.once("error", this._onError);
|
|
35507
|
-
handle2.once("close", this._onClose);
|
|
35508
|
-
if (handle2.stdin) {
|
|
35509
|
-
const { stdin } = options2;
|
|
35510
|
-
if (typeof stdin === "string") handle2.stdin.end(stdin);
|
|
35511
|
-
else stdin?.process?.stdout?.pipe(handle2.stdin);
|
|
35593
|
+
async refresh(site, now = Date.now()) {
|
|
35594
|
+
const installation = this.state.installation();
|
|
35595
|
+
if (!installation) return "unavailable";
|
|
35596
|
+
const last = this.state.db.prepare("SELECT refreshed_at FROM cli_analytics_identity WHERE id=1").get();
|
|
35597
|
+
if (last && now - last.refreshed_at < 5 * 6e4 && this.identity()) return "ok";
|
|
35598
|
+
try {
|
|
35599
|
+
this.updateIdentity(await createCliApi(site, this.fetcher, installation.token).call("me"), now);
|
|
35600
|
+
return "ok";
|
|
35601
|
+
} catch (error62) {
|
|
35602
|
+
if (error62 instanceof ApiClientError && error62.response?.error?.code === "installation-revoked") {
|
|
35603
|
+
this.state.db.exec("DELETE FROM cli_analytics_queue; DELETE FROM cli_analytics_identity");
|
|
35604
|
+
return "revoked";
|
|
35605
|
+
}
|
|
35606
|
+
return "unavailable";
|
|
35512
35607
|
}
|
|
35513
35608
|
}
|
|
35514
|
-
|
|
35515
|
-
|
|
35516
|
-
|
|
35517
|
-
|
|
35518
|
-
|
|
35519
|
-
|
|
35609
|
+
record(event, values = {}) {
|
|
35610
|
+
if (!EVENT.has(event)) return;
|
|
35611
|
+
const installation = this.state.installation();
|
|
35612
|
+
if (!installation) return;
|
|
35613
|
+
const identity2 = this.identity();
|
|
35614
|
+
if (identity2 && !identity2.enabled) return;
|
|
35615
|
+
this.state.db.prepare("INSERT INTO cli_analytics_queue (id,account_id,event,properties_json,occurred_at) VALUES (?,?,?,?,?)").run(randomUUID10(), installation.accountId, event, JSON.stringify(scrubEventProperties(event, values)), (/* @__PURE__ */ new Date()).toISOString());
|
|
35616
|
+
this.state.db.exec("DELETE FROM cli_analytics_queue WHERE id IN (SELECT id FROM cli_analytics_queue ORDER BY occurred_at DESC LIMIT -1 OFFSET 1000)");
|
|
35520
35617
|
}
|
|
35521
|
-
|
|
35522
|
-
|
|
35523
|
-
|
|
35524
|
-
|
|
35618
|
+
async flush() {
|
|
35619
|
+
const identity2 = this.identity();
|
|
35620
|
+
if (!identity2?.enabled) return;
|
|
35621
|
+
const rows = this.state.db.prepare("SELECT id,account_id,event,properties_json,occurred_at,attempts FROM cli_analytics_queue WHERE account_id=? AND next_attempt_at<=? ORDER BY occurred_at,id LIMIT 50").all(identity2.accountId, Date.now());
|
|
35622
|
+
if (!rows.length) return;
|
|
35623
|
+
const batch = rows.map((row) => ({ uuid: row.id, event: row.event, distinct_id: identity2.accountId, timestamp: row.occurred_at, properties: { ...JSON.parse(row.properties_json), schema_version: "apilift.analytics/v1", environment: identity2.environment, component: "cli", release: this.release, account_id: identity2.accountId, workspace_id: identity2.workspaceId, installation_id: identity2.installationId, is_internal: identity2.internal, $geoip_disable: true } }));
|
|
35624
|
+
let sent = false;
|
|
35625
|
+
try {
|
|
35626
|
+
sent = (await this.fetcher(`${identity2.host}/batch/`, { method: "POST", redirect: "error", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ api_key: identity2.projectKey, batch }), signal: AbortSignal.timeout(2e3) })).ok;
|
|
35627
|
+
} catch {
|
|
35525
35628
|
}
|
|
35526
|
-
|
|
35527
|
-
|
|
35528
|
-
|
|
35529
|
-
|
|
35530
|
-
}
|
|
35531
|
-
};
|
|
35532
|
-
x = (command6, args, userOptions) => {
|
|
35533
|
-
const proc = new ExecProcess(command6, args, userOptions);
|
|
35534
|
-
proc.spawn();
|
|
35535
|
-
return proc;
|
|
35629
|
+
for (const row of rows) {
|
|
35630
|
+
if (sent) this.state.db.prepare("DELETE FROM cli_analytics_queue WHERE id=?").run(row.id);
|
|
35631
|
+
else this.state.db.prepare("UPDATE cli_analytics_queue SET attempts=?,next_attempt_at=? WHERE id=?").run(Math.min(20, row.attempts + 1), Date.now() + Math.min(3600, 2 ** (row.attempts + 1)) * 1e3, row.id);
|
|
35632
|
+
}
|
|
35633
|
+
}
|
|
35536
35634
|
};
|
|
35537
|
-
|
|
35635
|
+
}
|
|
35636
|
+
});
|
|
35637
|
+
|
|
35638
|
+
// src/usage/process.ts
|
|
35639
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
35640
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
35641
|
+
function startCollector(env) {
|
|
35642
|
+
if (process.env.VITEST || env.VITEST || env.APILIFT_COLLECTOR_DISABLED === "1") return;
|
|
35643
|
+
const entry2 = fileURLToPath3(new URL("./apilift-collector.js", import.meta.url));
|
|
35644
|
+
if (!existsSync5(entry2)) return;
|
|
35645
|
+
try {
|
|
35646
|
+
startBackground(entry2, env, () => {
|
|
35647
|
+
});
|
|
35648
|
+
} catch {
|
|
35649
|
+
}
|
|
35650
|
+
}
|
|
35651
|
+
var init_process2 = __esm({
|
|
35652
|
+
"src/usage/process.ts"() {
|
|
35653
|
+
"use strict";
|
|
35654
|
+
init_process();
|
|
35538
35655
|
}
|
|
35539
35656
|
});
|
|
35540
35657
|
|
|
@@ -37573,16 +37690,79 @@ var init_compat2 = __esm({
|
|
|
37573
37690
|
});
|
|
37574
37691
|
|
|
37575
37692
|
// src/native-host/registration.ts
|
|
37576
|
-
import { createHash as createHash6 } from "node:crypto";
|
|
37693
|
+
import { createHash as createHash6, randomUUID as randomUUID11 } from "node:crypto";
|
|
37694
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
37695
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
37577
37696
|
import { homedir as homedir3, platform as platform2 } from "node:os";
|
|
37578
37697
|
import { dirname as dirname8, isAbsolute as isAbsolute4, join as join14, resolve as resolve4 } from "node:path";
|
|
37579
|
-
import { chmod as chmod2, mkdir, readFile, rename as rename2, writeFile, copyFile } from "node:fs/promises";
|
|
37580
|
-
function
|
|
37698
|
+
import { chmod as chmod2, mkdir, readFile, rename as rename2, writeFile, copyFile, rm, stat } from "node:fs/promises";
|
|
37699
|
+
function batchLiteral(value) {
|
|
37700
|
+
if (/["\r\n\0]/u.test(value)) throw new Error("Native host launcher values contain unsupported control characters");
|
|
37701
|
+
return value.replaceAll("%", "%%");
|
|
37702
|
+
}
|
|
37703
|
+
function nativeLauncher(values, windows) {
|
|
37704
|
+
const environment = { APILIFT_HOME: values.root, APILIFT_NATIVE_HOST_NAME: values.hostName, APILIFT_NATIVE_MESSAGING_DIR: values.manifestRoot, ...values.site ? { APILIFT_URL: values.site } : {} };
|
|
37705
|
+
if (windows) return `@echo off\r
|
|
37706
|
+
chcp 65001 >nul 2>&1\r
|
|
37707
|
+
setlocal DisableDelayedExpansion\r
|
|
37708
|
+
${Object.entries(environment).map(([key, value]) => `set "${key}=${batchLiteral(value)}"\r
|
|
37709
|
+
`).join("")}"${batchLiteral(values.nodePath)}" "${batchLiteral(values.hostScript)}" %*\r
|
|
37710
|
+
exit /b %errorlevel%\r
|
|
37711
|
+
`;
|
|
37712
|
+
return `#!/bin/sh
|
|
37713
|
+
${Object.entries(environment).map(([key, value]) => `${key}=${posixQuote(value)}`).join(" ")} exec ${posixQuote(values.nodePath)} ${posixQuote(values.hostScript)} "$@"
|
|
37714
|
+
`;
|
|
37715
|
+
}
|
|
37716
|
+
function readWindowsHostValues(hostName, run2 = execFileSync2) {
|
|
37717
|
+
if (!/^[a-z0-9_]+(?:\.[a-z0-9_]+)*$/u.test(hostName)) throw new Error("Invalid native host name");
|
|
37718
|
+
const script = `$ErrorActionPreference='Stop'; $results=@(); foreach($view in @('32','64')) {
|
|
37719
|
+
$base=[Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::CurrentUser,[Microsoft.Win32.RegistryView]('Registry'+$view));
|
|
37720
|
+
try {
|
|
37721
|
+
$key=$base.OpenSubKey('Software\\Google\\Chrome\\NativeMessagingHosts\\${hostName}');
|
|
37722
|
+
$kind=$null; $data=$null;
|
|
37723
|
+
if($null -ne $key) { try {
|
|
37724
|
+
$value=$key.GetValue('',$null,[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames);
|
|
37725
|
+
if($null -ne $value) { $kind=$key.GetValueKind('').ToString(); $data=[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject $value -Compress))); }
|
|
37726
|
+
} finally { $key.Dispose(); } }
|
|
37727
|
+
$results+=@{view=$view;present=($null -ne $key);kind=$kind;data=$data};
|
|
37728
|
+
} finally { $base.Dispose(); }
|
|
37729
|
+
}; ConvertTo-Json -InputObject @($results) -Compress`;
|
|
37730
|
+
try {
|
|
37731
|
+
const output2 = run2("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")], { encoding: "utf8", timeout: 1e4, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
37732
|
+
const values = JSON.parse(String(output2));
|
|
37733
|
+
if (!Array.isArray(values) || values.length !== 2) throw new Error("Invalid registry snapshot");
|
|
37734
|
+
return ["32", "64"].map((view) => {
|
|
37735
|
+
const items = values.filter((item2) => item2?.view === view);
|
|
37736
|
+
const item = items[0];
|
|
37737
|
+
if (items.length !== 1 || typeof item.present !== "boolean" || !(item.kind === null || typeof item.kind === "string") || !(item.data === null || typeof item.data === "string")) throw new Error("Invalid registry value");
|
|
37738
|
+
return { view, present: item.present, kind: item.kind, value: item.data === null ? null : JSON.parse(Buffer.from(item.data, "base64").toString("utf8")) };
|
|
37739
|
+
});
|
|
37740
|
+
} catch {
|
|
37741
|
+
throw new Error("Could not inspect the current user's Chrome native host registration");
|
|
37742
|
+
}
|
|
37743
|
+
}
|
|
37744
|
+
function registerWindowsHost(hostName, manifest, owned, run2 = execFileSync2, write = true, backup) {
|
|
37745
|
+
const key = `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`;
|
|
37746
|
+
const options2 = { encoding: "utf8", timeout: 1e4, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] };
|
|
37747
|
+
const present = /* @__PURE__ */ new Set();
|
|
37748
|
+
for (const value of readWindowsHostValues(hostName, run2)) {
|
|
37749
|
+
if (!value.present) continue;
|
|
37750
|
+
const { view } = value;
|
|
37751
|
+
present.add(view);
|
|
37752
|
+
const current = value.kind === "String" && typeof value.value === "string" ? value.value : null;
|
|
37753
|
+
if (!owned || current?.toLowerCase() !== manifest.toLowerCase()) {
|
|
37754
|
+
if (!backup) throw new Error(`Native host registration is not owned by Apilift: ${key}`);
|
|
37755
|
+
backup(view, JSON.stringify(value));
|
|
37756
|
+
}
|
|
37757
|
+
}
|
|
37758
|
+
if (write) for (const view of /* @__PURE__ */ new Set(["32", ...present])) run2("reg.exe", ["add", key, "/ve", "/t", "REG_SZ", "/d", manifest, "/f", `/reg:${view}`], options2);
|
|
37759
|
+
}
|
|
37760
|
+
function manifestDirectory(env = process.env, system = { platform: platform2(), home: homedir3() }) {
|
|
37581
37761
|
if (env.APILIFT_NATIVE_MESSAGING_DIR) return resolve4(env.APILIFT_NATIVE_MESSAGING_DIR);
|
|
37582
|
-
const home =
|
|
37583
|
-
if (
|
|
37584
|
-
if (
|
|
37585
|
-
return join14(home, ".config", "google-chrome", "NativeMessagingHosts");
|
|
37762
|
+
const home = system.home;
|
|
37763
|
+
if (system.platform === "darwin") return join14(home, "Library", "Application Support", "Google", "Chrome", "NativeMessagingHosts");
|
|
37764
|
+
if (system.platform === "win32") throw new Error("Windows native-host registration needs a data-root manifest and HKCU registry entry");
|
|
37765
|
+
return join14(absoluteEnv(env.CHROME_CONFIG_HOME) || absoluteEnv(env.XDG_CONFIG_HOME) || join14(home, ".config"), "google-chrome", "NativeMessagingHosts");
|
|
37586
37766
|
}
|
|
37587
37767
|
async function registerNativeHost(options2) {
|
|
37588
37768
|
const env = options2.env ?? process.env;
|
|
@@ -37597,7 +37777,24 @@ async function registerNativeHost(options2) {
|
|
|
37597
37777
|
const manifestRoot = env.APILIFT_NATIVE_MESSAGING_DIR ? resolve4(env.APILIFT_NATIVE_MESSAGING_DIR) : platform2() === "win32" ? nativeRoot : manifestDirectory(env);
|
|
37598
37778
|
const launcher = join14(nativeRoot, platform2() === "win32" ? "launcher.cmd" : "launcher.sh");
|
|
37599
37779
|
const manifest = join14(manifestRoot, `${hostName}.json`);
|
|
37780
|
+
const manifests = [manifest];
|
|
37781
|
+
if (platform2() === "linux" && !env.APILIFT_NATIVE_MESSAGING_DIR) {
|
|
37782
|
+
for (const browser of ["google-chrome-beta", "google-chrome-unstable", "chromium"]) {
|
|
37783
|
+
const profile = join14(dirname8(dirname8(manifestRoot)), browser);
|
|
37784
|
+
if (await stat(profile).then((value) => value.isDirectory()).catch(() => false)) manifests.push(join14(profile, "NativeMessagingHosts", `${hostName}.json`));
|
|
37785
|
+
}
|
|
37786
|
+
}
|
|
37600
37787
|
const receiptPath = join14(nativeRoot, "registration.json");
|
|
37788
|
+
const registryBackup = options2.allowReplaceUnowned ? (view, value) => {
|
|
37789
|
+
const directory = join14(nativeRoot, "backup");
|
|
37790
|
+
mkdirSync10(directory, { recursive: true, mode: 448 });
|
|
37791
|
+
const path2 = join14(directory, `${hostName}-registry-${view}-${fingerprint(value)}.json`);
|
|
37792
|
+
try {
|
|
37793
|
+
writeFileSync9(path2, JSON.stringify({ hostName, view, query: value }), { flag: "wx", mode: 384 });
|
|
37794
|
+
} catch (error62) {
|
|
37795
|
+
if (error62.code !== "EEXIST") throw error62;
|
|
37796
|
+
}
|
|
37797
|
+
} : void 0;
|
|
37601
37798
|
const previous = await readFile(receiptPath, "utf8").then((value) => JSON.parse(value)).catch(() => ({}));
|
|
37602
37799
|
const guard = async (path2) => {
|
|
37603
37800
|
const bytes = await readFile(path2).catch(() => null);
|
|
@@ -37607,36 +37804,36 @@ async function registerNativeHost(options2) {
|
|
|
37607
37804
|
await copyFile(path2, join14(nativeRoot, "backup", `${fingerprint(bytes)}-${Date.now()}`));
|
|
37608
37805
|
};
|
|
37609
37806
|
await guard(launcher);
|
|
37610
|
-
await guard(
|
|
37807
|
+
for (const path2 of manifests) await guard(path2);
|
|
37808
|
+
if (platform2() === "win32" && !env.APILIFT_NATIVE_MESSAGING_DIR) {
|
|
37809
|
+
const bytes = await readFile(manifest).catch(() => null);
|
|
37810
|
+
registerWindowsHost(hostName, manifest, Boolean(bytes && previous[manifest] === fingerprint(bytes)), execFileSync2, false, registryBackup);
|
|
37811
|
+
}
|
|
37611
37812
|
await mkdir(nativeRoot, { recursive: true, mode: 448 });
|
|
37612
37813
|
await mkdir(manifestRoot, { recursive: true, mode: 448 });
|
|
37613
|
-
const launcherText = platform2() === "win32"
|
|
37614
|
-
set "APILIFT_HOME=${root}"\r
|
|
37615
|
-
set "APILIFT_NATIVE_HOST_NAME=${hostName}"\r
|
|
37616
|
-
${siteUrl2 ? `set "APILIFT_URL=${siteUrl2.origin}"\r
|
|
37617
|
-
` : ""}${env.APILIFT_NATIVE_MESSAGING_DIR ? `set "APILIFT_NATIVE_MESSAGING_DIR=${manifestRoot}"\r
|
|
37618
|
-
` : ""}"${nodePath}" "${hostScript}" %*\r
|
|
37619
|
-
` : `#!/bin/sh
|
|
37620
|
-
APILIFT_HOME=${posixQuote(root)} APILIFT_NATIVE_HOST_NAME=${posixQuote(hostName)} ${siteUrl2 ? `APILIFT_URL=${posixQuote(siteUrl2.origin)} ` : ""}${env.APILIFT_NATIVE_MESSAGING_DIR ? `APILIFT_NATIVE_MESSAGING_DIR=${posixQuote(manifestRoot)} ` : ""}exec ${posixQuote(nodePath)} ${posixQuote(hostScript)} "$@"
|
|
37621
|
-
`;
|
|
37814
|
+
const launcherText = nativeLauncher({ root, hostName, nodePath, hostScript, manifestRoot, site: siteUrl2?.origin }, platform2() === "win32");
|
|
37622
37815
|
const manifestText = JSON.stringify({ name: hostName, description: "Apilift browser bridge", path: launcher, type: "stdio", allowed_origins: [`chrome-extension://${options2.extensionId}/`] }, null, 2) + "\n";
|
|
37623
37816
|
const atomicWrite = async (path2, bytes, mode) => {
|
|
37624
|
-
const temp = join14(dirname8(path2), `.${hostName}-${
|
|
37625
|
-
|
|
37626
|
-
|
|
37627
|
-
|
|
37817
|
+
const temp = join14(dirname8(path2), `.${hostName}-${randomUUID11()}.tmp`);
|
|
37818
|
+
try {
|
|
37819
|
+
await writeFile(temp, bytes, { mode, flag: "wx" });
|
|
37820
|
+
await chmod2(temp, mode);
|
|
37821
|
+
await rename2(temp, path2);
|
|
37822
|
+
} finally {
|
|
37823
|
+
await rm(temp, { force: true });
|
|
37824
|
+
}
|
|
37628
37825
|
};
|
|
37629
37826
|
await atomicWrite(launcher, launcherText, platform2() === "win32" ? 384 : 448);
|
|
37630
|
-
|
|
37631
|
-
|
|
37632
|
-
|
|
37633
|
-
if (platform2() === "win32" && !env.APILIFT_NATIVE_MESSAGING_DIR) {
|
|
37634
|
-
const { execFileSync: execFileSync3 } = await import("node:child_process");
|
|
37635
|
-
execFileSync3("reg.exe", ["add", `HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${hostName}`, "/ve", "/t", "REG_SZ", "/d", manifest, "/f"], { stdio: "ignore" });
|
|
37827
|
+
for (const path2 of manifests) {
|
|
37828
|
+
await mkdir(dirname8(path2), { recursive: true, mode: 448 });
|
|
37829
|
+
await atomicWrite(path2, manifestText, 384);
|
|
37636
37830
|
}
|
|
37831
|
+
const receipt = { ...previous, [launcher]: fingerprint(launcherText), ...Object.fromEntries(manifests.map((path2) => [path2, fingerprint(manifestText)])) };
|
|
37832
|
+
await atomicWrite(receiptPath, JSON.stringify(receipt, null, 2) + "\n", 384);
|
|
37833
|
+
if (platform2() === "win32" && !env.APILIFT_NATIVE_MESSAGING_DIR) registerWindowsHost(hostName, manifest, true, execFileSync2, true, registryBackup);
|
|
37637
37834
|
return { launcher, manifest, hostName };
|
|
37638
37835
|
}
|
|
37639
|
-
var fingerprint, hostNames, validId, posixQuote;
|
|
37836
|
+
var fingerprint, hostNames, validId, posixQuote, absoluteEnv;
|
|
37640
37837
|
var init_registration = __esm({
|
|
37641
37838
|
"src/native-host/registration.ts"() {
|
|
37642
37839
|
"use strict";
|
|
@@ -37644,13 +37841,14 @@ var init_registration = __esm({
|
|
|
37644
37841
|
hostNames = /* @__PURE__ */ new Set(["com.apilift.browser", "com.apilift.browser.dev"]);
|
|
37645
37842
|
validId = /^[a-p]{32}$/;
|
|
37646
37843
|
posixQuote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
37844
|
+
absoluteEnv = (value) => value && isAbsolute4(value) ? value : void 0;
|
|
37647
37845
|
}
|
|
37648
37846
|
});
|
|
37649
37847
|
|
|
37650
37848
|
// src/update.ts
|
|
37651
37849
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
37652
|
-
import { dirname as dirname9, join as join15, resolve as resolve5, sep } from "node:path";
|
|
37653
|
-
import { mkdirSync as
|
|
37850
|
+
import { dirname as dirname9, join as join15, resolve as resolve5, sep, isAbsolute as isAbsolute5 } from "node:path";
|
|
37851
|
+
import { mkdirSync as mkdirSync11, realpathSync as realpathSync2, writeFileSync as writeFileSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
37654
37852
|
import { DatabaseSync as DatabaseSync6 } from "node:sqlite";
|
|
37655
37853
|
function globalPackage(script, prefix) {
|
|
37656
37854
|
const canonical = (path2) => {
|
|
@@ -37664,22 +37862,52 @@ function globalPackage(script, prefix) {
|
|
|
37664
37862
|
const base2 = canonical(prefix).toLowerCase();
|
|
37665
37863
|
return [join15(base2, "lib", "node_modules", "@apilift", "cli"), join15(base2, "node_modules", "@apilift", "cli")].some((path2) => normalized.startsWith(`${path2}${sep}`));
|
|
37666
37864
|
}
|
|
37865
|
+
async function pnpmInstallations(runner, env) {
|
|
37866
|
+
const listed = await runner("pnpm", ["list", "-g", "@apilift/cli", "--depth", "0", "--json"], 1e4, env).catch(() => null);
|
|
37867
|
+
if (listed?.exitCode !== 0) return [];
|
|
37868
|
+
try {
|
|
37869
|
+
const groups = JSON.parse(listed.stdout);
|
|
37870
|
+
if (!Array.isArray(groups)) return [];
|
|
37871
|
+
return groups.flatMap((group) => {
|
|
37872
|
+
const pkg = group?.dependencies?.["@apilift/cli"];
|
|
37873
|
+
return pkg && typeof pkg.path === "string" && isAbsolute5(pkg.path) && typeof pkg.version === "string" ? [{ entrypoint: join15(pkg.path, "dist", "apilift.js"), version: pkg.version }] : [];
|
|
37874
|
+
});
|
|
37875
|
+
} catch {
|
|
37876
|
+
return [];
|
|
37877
|
+
}
|
|
37878
|
+
}
|
|
37879
|
+
async function installationManager(script, runner, env) {
|
|
37880
|
+
const prefix = await runner("npm", ["prefix", "-g"], 1e4, env).catch(() => null);
|
|
37881
|
+
if (prefix?.exitCode === 0 && globalPackage(script, prefix.stdout.trim())) return { manager: "npm", entrypoint: script };
|
|
37882
|
+
const canonical = (path2) => {
|
|
37883
|
+
try {
|
|
37884
|
+
return realpathSync2(path2);
|
|
37885
|
+
} catch {
|
|
37886
|
+
return resolve5(path2);
|
|
37887
|
+
}
|
|
37888
|
+
};
|
|
37889
|
+
const selected = (await pnpmInstallations(runner, env)).find((candidate2) => canonical(candidate2.entrypoint) === canonical(script));
|
|
37890
|
+
return selected ? { manager: "pnpm", entrypoint: selected.entrypoint } : null;
|
|
37891
|
+
}
|
|
37667
37892
|
async function maybeAutoUpdate(options2) {
|
|
37668
37893
|
if (options2.env.APILIFT_AUTO_UPDATE === "0" || options2.env.CI || options2.env.APILIFT_DEV_PLUGIN_ROOT || options2.env.APILIFT_UPDATE_REEXEC === "1") return null;
|
|
37669
37894
|
const current = options2.current || CURRENT, runner = options2.runner || run, script = options2.script || fileURLToPath4(import.meta.url);
|
|
37670
37895
|
if (!shouldCheckUpdate(options2.state, current)) return null;
|
|
37671
|
-
const
|
|
37672
|
-
if (!
|
|
37896
|
+
const installation = await installationManager(script, runner, options2.env);
|
|
37897
|
+
if (!installation) return null;
|
|
37673
37898
|
markUpdateChecked(options2.state, current);
|
|
37674
|
-
|
|
37899
|
+
let updatedEntry = installation.entrypoint;
|
|
37900
|
+
const update = await updateCli({ ...options2, current, runner, script, manual: false }, (entrypoint) => {
|
|
37901
|
+
updatedEntry = entrypoint;
|
|
37902
|
+
});
|
|
37675
37903
|
if (update.stderr.startsWith("update-incomplete")) return update;
|
|
37676
37904
|
if (!update.stdout.startsWith("Apilift ") || !update.stdout.includes(" was installed.")) return null;
|
|
37677
|
-
const result3 = await runner(process.execPath, [
|
|
37905
|
+
const result3 = await runner(process.execPath, [updatedEntry, ...options2.argv], 18e4, { ...process.env, ...options2.env, APILIFT_UPDATE_REEXEC: "1" });
|
|
37678
37906
|
return { stdout: result3.stdout, stderr: result3.stderr, exitCode: result3.exitCode ?? 1, dispatched: false };
|
|
37679
37907
|
}
|
|
37680
37908
|
function lock(root) {
|
|
37681
37909
|
const dir = join15(root, "locks");
|
|
37682
|
-
|
|
37910
|
+
mkdirSync11(dir, { recursive: true, mode: 448 });
|
|
37683
37911
|
const db = new DatabaseSync6(join15(dir, "self-update.sqlite"));
|
|
37684
37912
|
db.exec("PRAGMA busy_timeout=0");
|
|
37685
37913
|
try {
|
|
@@ -37693,15 +37921,15 @@ function lock(root) {
|
|
|
37693
37921
|
function message(stdout, exitCode = 0, stderr = "") {
|
|
37694
37922
|
return { stdout, stderr, exitCode, dispatched: false };
|
|
37695
37923
|
}
|
|
37696
|
-
async function updateCli(options2) {
|
|
37924
|
+
async function updateCli(options2, onInstalled) {
|
|
37697
37925
|
const current = options2.current || CURRENT;
|
|
37698
37926
|
const runner = options2.runner || run;
|
|
37699
37927
|
let latest;
|
|
37700
37928
|
let linkedAgents = [];
|
|
37701
37929
|
try {
|
|
37702
|
-
const
|
|
37703
|
-
if (
|
|
37704
|
-
const me2 = await createCliApi(options2.site, options2.fetcher || fetch,
|
|
37930
|
+
const installation2 = options2.state.installation();
|
|
37931
|
+
if (installation2) {
|
|
37932
|
+
const me2 = await createCliApi(options2.site, options2.fetcher || fetch, installation2.token).call("me");
|
|
37705
37933
|
latest = me2.compatibility.latest.cli;
|
|
37706
37934
|
linkedAgents = me2.installation.agents;
|
|
37707
37935
|
} else latest = (await createCliApi(options2.site, options2.fetcher || fetch).call("currentRelease")).components.cli.version;
|
|
@@ -37713,30 +37941,41 @@ async function updateCli(options2) {
|
|
|
37713
37941
|
if (compatible2(current, latest)) return message("The installed CLI and its required local components are up to date.\nNo installation changes were made. Continue the app work you were working on.\n");
|
|
37714
37942
|
if (!options2.manual && (options2.env.APILIFT_AUTO_UPDATE === "0" || options2.env.CI || options2.env.APILIFT_DEV_PLUGIN_ROOT || options2.env.npm_execpath?.includes("npx"))) return message("", 5, `client-upgrade-required \u2014 Install Apilift ${latest} through the supported package installation, then retry.
|
|
37715
37943
|
`);
|
|
37716
|
-
const prefix = await runner("npm", ["prefix", "-g"], 1e4);
|
|
37717
37944
|
const script = options2.script || fileURLToPath4(import.meta.url);
|
|
37718
|
-
|
|
37945
|
+
const installation = await installationManager(script, runner, options2.env);
|
|
37946
|
+
if (!installation) return message("", 5, `client-upgrade-required \u2014 This CLI is not a global npm or pnpm installation. Install Apilift ${latest} through your installation method, then retry.
|
|
37719
37947
|
`);
|
|
37948
|
+
const { manager } = installation;
|
|
37949
|
+
let entrypoint = installation.entrypoint;
|
|
37720
37950
|
const held = lock(options2.root);
|
|
37721
37951
|
if (!held) return message("", 5, "update-in-progress \u2014 Another Apilift update is running. Retry after it finishes.\n");
|
|
37722
37952
|
try {
|
|
37723
|
-
const installed = await runner(
|
|
37724
|
-
if (installed
|
|
37953
|
+
const installed = await runner(manager, [manager === "pnpm" ? "add" : "install", "-g", `@apilift/cli@${latest}`], 18e4, options2.env).catch(() => null);
|
|
37954
|
+
if (installed?.exitCode !== 0) return message("", 5, `update-failed \u2014 ${manager} could not finish installing the requested version. Run apilift --version to check the installed version, then retry apilift update.
|
|
37955
|
+
`);
|
|
37725
37956
|
options2.state.db.exec("CREATE TABLE IF NOT EXISTS cli_update_state (id INTEGER PRIMARY KEY CHECK(id=1), version TEXT NOT NULL, updated_at TEXT NOT NULL)");
|
|
37726
37957
|
options2.state.db.prepare("INSERT INTO cli_update_state (id,version,updated_at) VALUES (1,?,?) ON CONFLICT(id) DO UPDATE SET version=excluded.version,updated_at=excluded.updated_at").run(latest, (/* @__PURE__ */ new Date()).toISOString());
|
|
37727
37958
|
const nativeRoot = join15(options2.root, "native-host");
|
|
37728
|
-
|
|
37729
|
-
|
|
37959
|
+
mkdirSync11(nativeRoot, { recursive: true, mode: 448 });
|
|
37960
|
+
writeFileSync10(join15(nativeRoot, "restart-required.json"), `${JSON.stringify({ version: latest })}
|
|
37730
37961
|
`, { mode: 384 });
|
|
37731
37962
|
try {
|
|
37732
|
-
|
|
37963
|
+
if (manager === "pnpm") {
|
|
37964
|
+
const candidates = (await pnpmInstallations(runner, options2.env)).filter((candidate2) => candidate2.version === latest);
|
|
37965
|
+
if (candidates.length !== 1) throw new Error("Updated pnpm installation is ambiguous or unavailable");
|
|
37966
|
+
entrypoint = candidates[0].entrypoint;
|
|
37967
|
+
const pkg = JSON.parse(readFileSync10(join15(dirname9(entrypoint), "..", "package.json"), "utf8"));
|
|
37968
|
+
if (pkg.name !== "@apilift/cli" || pkg.version !== latest) throw new Error("Updated pnpm package could not be verified");
|
|
37969
|
+
}
|
|
37970
|
+
await registerNativeHost({ root: options2.root, hostScript: join15(dirname9(entrypoint), "apilift-native-host.js"), extensionId: options2.env.APILIFT_DEV_EXTENSION_ID || STORE_EXTENSION_ID, hostName: options2.env.APILIFT_NATIVE_HOST_NAME, siteUrl: options2.site, env: options2.env });
|
|
37733
37971
|
for (const agent2 of linkedAgents) {
|
|
37734
37972
|
if (!ensureAgentPlugin(agent2, options2.env).ready) throw new Error("Updated agent plugin activation is unverified");
|
|
37735
37973
|
}
|
|
37736
37974
|
} catch {
|
|
37737
|
-
return message("", 5, `update-incomplete \u2014 Apilift ${latest} was installed, but local component registration needs repair. Run apilift setup continue, then apilift doctor. Do not repeat the
|
|
37975
|
+
return message("", 5, `update-incomplete \u2014 Apilift ${latest} was installed, but local component registration needs repair. Run apilift setup continue, then apilift doctor. Do not repeat the package installation.
|
|
37738
37976
|
`);
|
|
37739
37977
|
}
|
|
37978
|
+
onInstalled?.(entrypoint);
|
|
37740
37979
|
return message(`Apilift ${latest} was installed. Continue the app work you were working on.
|
|
37741
37980
|
`);
|
|
37742
37981
|
} finally {
|
|
@@ -37762,15 +38001,15 @@ var init_update = __esm({
|
|
|
37762
38001
|
init_version();
|
|
37763
38002
|
init_registration();
|
|
37764
38003
|
init_plugin();
|
|
37765
|
-
run = async (command6, args, timeout, env) => await x(command6, args, { timeout, throwOnError: false,
|
|
38004
|
+
run = async (command6, args, timeout, env) => await x(command6, args, { timeout, throwOnError: false, nodeOptions: { windowsHide: true, env: { ...process.env, ...env } } });
|
|
37766
38005
|
CURRENT = cliVersion;
|
|
37767
38006
|
STORE_EXTENSION_ID = "fcndhdoedflmfmckkgpkdhmglgepbhnd";
|
|
37768
38007
|
}
|
|
37769
38008
|
});
|
|
37770
38009
|
|
|
37771
38010
|
// src/setup-check.ts
|
|
37772
|
-
import { createHash as createHash7, randomUUID as
|
|
37773
|
-
import { existsSync as existsSync6, readFileSync as
|
|
38011
|
+
import { createHash as createHash7, randomUUID as randomUUID12 } from "node:crypto";
|
|
38012
|
+
import { existsSync as existsSync6, readFileSync as readFileSync11, realpathSync as realpathSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
37774
38013
|
import { dirname as dirname10, join as join16 } from "node:path";
|
|
37775
38014
|
async function setupCheckBody(client, scopeId, value) {
|
|
37776
38015
|
if (typeof value.body === "string") return Buffer.byteLength(value.body, "utf8") <= maxCheckBodyBytes ? value.body : null;
|
|
@@ -37797,12 +38036,12 @@ function challengeFile(root, agent2) {
|
|
|
37797
38036
|
function setupChallenge(root, agent2, site) {
|
|
37798
38037
|
const file2 = challengeFile(root, agent2);
|
|
37799
38038
|
try {
|
|
37800
|
-
const saved = JSON.parse(
|
|
38039
|
+
const saved = JSON.parse(readFileSync11(file2, "utf8"));
|
|
37801
38040
|
if (new URL(saved.url).origin === site && Number.isFinite(saved.createdAt) && Date.now() - saved.createdAt < 10 * 6e4) return saved;
|
|
37802
38041
|
} catch {
|
|
37803
38042
|
}
|
|
37804
|
-
const challenge = { url: `${site}/setup-check?challenge=${
|
|
37805
|
-
|
|
38043
|
+
const challenge = { url: `${site}/setup-check?challenge=${randomUUID12()}`, createdAt: Date.now() };
|
|
38044
|
+
writeFileSync11(file2, JSON.stringify(challenge), { mode: 384 });
|
|
37806
38045
|
return challenge;
|
|
37807
38046
|
}
|
|
37808
38047
|
async function setupBridge(root) {
|
|
@@ -37812,6 +38051,22 @@ async function setupBridge(root) {
|
|
|
37812
38051
|
if (!client.legacyBridge) await waitForBridge(root, cliVersion, Math.max(0, 9e4 - (Date.now() - startedAt)));
|
|
37813
38052
|
return client;
|
|
37814
38053
|
}
|
|
38054
|
+
async function setupReadiness(api, waitForReport, timeoutMs = 1e4) {
|
|
38055
|
+
const deadline = Date.now() + timeoutMs;
|
|
38056
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
38057
|
+
let readiness2 = await api.call("updateReadiness", { body: {}, ...waitForReport ? { signal } : {} });
|
|
38058
|
+
while (waitForReport && (!readiness2.machine.nativeHostReady || !readiness2.machine.extensionReady) && Date.now() < deadline) {
|
|
38059
|
+
await new Promise((resolve6) => setTimeout(resolve6, Math.min(250, Math.max(0, deadline - Date.now()))));
|
|
38060
|
+
if (signal.aborted || Date.now() >= deadline) break;
|
|
38061
|
+
try {
|
|
38062
|
+
readiness2 = await api.call("updateReadiness", { body: {}, signal });
|
|
38063
|
+
} catch (error62) {
|
|
38064
|
+
if (signal.aborted) break;
|
|
38065
|
+
throw error62;
|
|
38066
|
+
}
|
|
38067
|
+
}
|
|
38068
|
+
return readiness2;
|
|
38069
|
+
}
|
|
37815
38070
|
async function verifySetupCheck(root, challenge) {
|
|
37816
38071
|
const client = await setupBridge(root);
|
|
37817
38072
|
const pageOrigin = new URL(challenge.url).origin;
|
|
@@ -37820,7 +38075,7 @@ async function verifySetupCheck(root, challenge) {
|
|
|
37820
38075
|
const inspect = await client.openScope({ kind: "inspect", ...scopeInput });
|
|
37821
38076
|
let candidates = [];
|
|
37822
38077
|
try {
|
|
37823
|
-
const deadline = Date.now() +
|
|
38078
|
+
const deadline = Date.now() + 1e4;
|
|
37824
38079
|
do {
|
|
37825
38080
|
candidates = (await client.candidates(inspect.id)).candidates;
|
|
37826
38081
|
if (candidates.length) break;
|
|
@@ -37831,7 +38086,7 @@ async function verifySetupCheck(root, challenge) {
|
|
|
37831
38086
|
}
|
|
37832
38087
|
if (candidates.length !== 1) return { ok: false, reason: candidates.length ? "More than one exact check tab matched" : "The extension did not report the exact check tab within 10 seconds" };
|
|
37833
38088
|
const execute = await client.openScope({ kind: "execute", tabSelector: candidates[0].selector, ...scopeInput });
|
|
37834
|
-
const id2 =
|
|
38089
|
+
const id2 = randomUUID12();
|
|
37835
38090
|
try {
|
|
37836
38091
|
await client.enqueueJob(execute.id, { job: { id: id2, kind: "replay", effect: "read", method: "GET", url: challenge.url, headers: {}, pageOrigin, allowedRequestOrigin: pageOrigin, timeoutMs: 2e4 } });
|
|
37837
38092
|
const deadline = Date.now() + 3e4;
|
|
@@ -38065,13 +38320,15 @@ Fix the local Chrome registration and retry:
|
|
|
38065
38320
|
${prefix} setup continue
|
|
38066
38321
|
`);
|
|
38067
38322
|
}
|
|
38068
|
-
let bridgeError;
|
|
38323
|
+
let bridgeError, connected = false;
|
|
38069
38324
|
try {
|
|
38070
|
-
await setupBridge(dataRoot(env));
|
|
38325
|
+
connected = !(await setupBridge(dataRoot(env))).legacyBridge;
|
|
38071
38326
|
} catch (error62) {
|
|
38072
38327
|
bridgeError = error62;
|
|
38073
38328
|
}
|
|
38074
|
-
const readiness2 = await api
|
|
38329
|
+
const readiness2 = await setupReadiness(api, connected);
|
|
38330
|
+
if (connected && (!readiness2.machine.nativeHostReady || !readiness2.machine.extensionReady)) return result2("", 5, `registry-readiness-pending \u2014 Chrome connected, but this installation's readiness report is still pending. Keep Chrome open and retry ${prefix} setup continue.
|
|
38331
|
+
`);
|
|
38075
38332
|
if (!readiness2.machine.nativeHostReady || !readiness2.machine.extensionReady) return { ...result2(`${JSON.stringify({ action: "user", userMessage: extensionUserMessage(env.APILIFT_DEV_EXTENSION_PATH), resumeCommand: `${prefix} setup continue` })}
|
|
38076
38333
|
`), stdoutJson: true };
|
|
38077
38334
|
if (bridgeError) return result2("", 5, `extension-unavailable \u2014 ${bridgeError instanceof Error ? bridgeError.message : "Chrome did not respond"}. Check native host and extension setup with ${prefix} doctor.
|
|
@@ -38228,7 +38485,7 @@ var init_cli = __esm({
|
|
|
38228
38485
|
init_state();
|
|
38229
38486
|
init_analytics2();
|
|
38230
38487
|
init_ledger();
|
|
38231
|
-
|
|
38488
|
+
init_process2();
|
|
38232
38489
|
init_update();
|
|
38233
38490
|
init_version();
|
|
38234
38491
|
init_setup_check();
|