free-pi-cli 0.4.3 → 0.4.5
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/index-xkn61g24.js +17974 -0
- package/dist/index.js +1 -1
- package/dist/{main-xn8n5cb2.js → main-r61kpjqw.js} +277 -79
- package/package.json +3 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/main.ts
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
|
+
import { dirname as dirname5, join as join5 } from "node:path";
|
|
5
6
|
|
|
6
7
|
// src/browser.ts
|
|
7
8
|
import { spawn } from "node:child_process";
|
|
@@ -44,7 +45,7 @@ function openBrowser(url, platform = process.platform, spawnImpl = spawn) {
|
|
|
44
45
|
// package.json
|
|
45
46
|
var package_default = {
|
|
46
47
|
name: "free-pi-cli",
|
|
47
|
-
version: "0.4.
|
|
48
|
+
version: "0.4.5",
|
|
48
49
|
description: "Free, ad-supported distribution of the pi coding agent. Inference paid for by ads.",
|
|
49
50
|
license: "MIT",
|
|
50
51
|
type: "module",
|
|
@@ -64,7 +65,8 @@ var package_default = {
|
|
|
64
65
|
prepublishOnly: "bun run build"
|
|
65
66
|
},
|
|
66
67
|
dependencies: {
|
|
67
|
-
"@earendil-works/pi-coding-agent": "1.2.0"
|
|
68
|
+
"@earendil-works/pi-coding-agent": "1.2.0",
|
|
69
|
+
"@gravity-ai/api": "1.2.1"
|
|
68
70
|
},
|
|
69
71
|
devDependencies: {
|
|
70
72
|
"@freepi/pi-ads": "workspace:*",
|
|
@@ -92,6 +94,7 @@ Usage:
|
|
|
92
94
|
Environment:
|
|
93
95
|
FREEPI_BASE_URL override the backend base URL (default https://api.freepi.ai)
|
|
94
96
|
FREEPI_NO_AUTO_UPDATE disable in-place self-update for this run
|
|
97
|
+
FREEPI_NO_GRAVITY_PIXEL=1 do not run Gravity's ad-measurement pixel
|
|
95
98
|
`.trim();
|
|
96
99
|
function versionLine() {
|
|
97
100
|
return `free-pi-cli ${CLI_VERSION}`;
|
|
@@ -222,18 +225,8 @@ function getConfigPath() {
|
|
|
222
225
|
return join2(homedir(), FREE_PI_DIR_NAME, "config.json");
|
|
223
226
|
}
|
|
224
227
|
|
|
225
|
-
// src/
|
|
226
|
-
import {
|
|
227
|
-
createAgentSessionFromServices,
|
|
228
|
-
createAgentSessionRuntime,
|
|
229
|
-
createAgentSessionServices,
|
|
230
|
-
createCodemodeExtension,
|
|
231
|
-
createMcpExtension,
|
|
232
|
-
createToolSearchExtension,
|
|
233
|
-
InteractiveMode,
|
|
234
|
-
SessionManager,
|
|
235
|
-
SettingsManager
|
|
236
|
-
} from "@earendil-works/pi-coding-agent";
|
|
228
|
+
// src/gravity-pixel.ts
|
|
229
|
+
import { createHash } from "node:crypto";
|
|
237
230
|
|
|
238
231
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
239
232
|
var _a;
|
|
@@ -4876,11 +4869,16 @@ var AdNextResponseSchema = object({
|
|
|
4876
4869
|
ad_id: string2(),
|
|
4877
4870
|
click_token: string2(),
|
|
4878
4871
|
creative: AdCreativeSchema,
|
|
4879
|
-
click_url: string2()
|
|
4872
|
+
click_url: string2(),
|
|
4873
|
+
source: _enum(["gravity", "own"]).optional(),
|
|
4874
|
+
imp_url: string2().optional()
|
|
4880
4875
|
});
|
|
4876
|
+
var GRAVITY_CONTEXT_HEADER = "x-gravity-context";
|
|
4877
|
+
var GRAVITY_CONTEXT_MAX_BYTES = 8192;
|
|
4881
4878
|
var AdImpressionRequestSchema = object({
|
|
4882
4879
|
ad_id: string2(),
|
|
4883
|
-
click_token: string2()
|
|
4880
|
+
click_token: string2(),
|
|
4881
|
+
imp_fired: boolean2().optional()
|
|
4884
4882
|
});
|
|
4885
4883
|
var AdminAdRequestSchema = object({
|
|
4886
4884
|
slot: AdSlotSchema,
|
|
@@ -5087,6 +5085,83 @@ function formatCreditsLeftLine(remaining, allowance, refillAt) {
|
|
|
5087
5085
|
return `${left} / ${total} credits left today · refills ${formatRefillEt(refillAt)}`;
|
|
5088
5086
|
}
|
|
5089
5087
|
var SLOW_LANE_METER_LINE = "Slow lane: cheapest model until refill";
|
|
5088
|
+
// src/gravity-pixel.ts
|
|
5089
|
+
var GRAVITY_PIXEL_ID = "6cd74804-0541-4d9b-899d-d7fceb465b6f";
|
|
5090
|
+
function userIdFromJwt(jwt) {
|
|
5091
|
+
try {
|
|
5092
|
+
const payload = JSON.parse(Buffer.from(jwt.split(".")[1] ?? "", "base64url").toString("utf8"));
|
|
5093
|
+
return typeof payload.sub === "string" ? payload.sub : undefined;
|
|
5094
|
+
} catch {
|
|
5095
|
+
return;
|
|
5096
|
+
}
|
|
5097
|
+
}
|
|
5098
|
+
function dropPixelSignalHandlers() {
|
|
5099
|
+
const onNew = (event, fn) => {
|
|
5100
|
+
if (event !== "SIGINT" && event !== "SIGTERM" || typeof fn !== "function")
|
|
5101
|
+
return;
|
|
5102
|
+
if (!/shutdownSync/.test(Function.prototype.toString.call(fn)))
|
|
5103
|
+
return;
|
|
5104
|
+
queueMicrotask(() => process.removeListener(event, fn));
|
|
5105
|
+
};
|
|
5106
|
+
process.on("newListener", onNew);
|
|
5107
|
+
return () => {
|
|
5108
|
+
process.removeListener("newListener", onNew);
|
|
5109
|
+
};
|
|
5110
|
+
}
|
|
5111
|
+
function startGravityPixel(jwt, storageDir, env = process.env, load = () => import("./index-xkn61g24.js")) {
|
|
5112
|
+
if (env.FREEPI_NO_GRAVITY_PIXEL === "1")
|
|
5113
|
+
return;
|
|
5114
|
+
const userId = userIdFromJwt(jwt);
|
|
5115
|
+
if (!userId)
|
|
5116
|
+
return;
|
|
5117
|
+
const userHash = createHash("sha256").update(userId).digest("hex");
|
|
5118
|
+
let sdk;
|
|
5119
|
+
let pixel;
|
|
5120
|
+
(async () => {
|
|
5121
|
+
try {
|
|
5122
|
+
sdk = await load();
|
|
5123
|
+
const p = sdk.gravityPixel({ pixelId: GRAVITY_PIXEL_ID, appName: "free-pi", storageDir });
|
|
5124
|
+
pixel = p;
|
|
5125
|
+
const stopWatching = dropPixelSignalHandlers();
|
|
5126
|
+
try {
|
|
5127
|
+
await p.start();
|
|
5128
|
+
} finally {
|
|
5129
|
+
stopWatching();
|
|
5130
|
+
}
|
|
5131
|
+
} catch {
|
|
5132
|
+
pixel = undefined;
|
|
5133
|
+
}
|
|
5134
|
+
})();
|
|
5135
|
+
return () => {
|
|
5136
|
+
try {
|
|
5137
|
+
const sessionId = pixel?.getSessionId();
|
|
5138
|
+
if (!sdk || !pixel || !sessionId)
|
|
5139
|
+
return;
|
|
5140
|
+
const ctx = sdk.gravityContext({
|
|
5141
|
+
sessionId,
|
|
5142
|
+
user: { userId: userHash, gruid: pixel.getVisitorId(), grclid: pixel.getClickId(), graid: pixel.getGraid() }
|
|
5143
|
+
});
|
|
5144
|
+
const encoded = Buffer.from(JSON.stringify(ctx)).toString("base64url");
|
|
5145
|
+
return encoded.length <= GRAVITY_CONTEXT_MAX_BYTES ? encoded : undefined;
|
|
5146
|
+
} catch {
|
|
5147
|
+
return;
|
|
5148
|
+
}
|
|
5149
|
+
};
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
// src/pi-launch.ts
|
|
5153
|
+
import {
|
|
5154
|
+
createAgentSessionFromServices,
|
|
5155
|
+
createAgentSessionRuntime,
|
|
5156
|
+
createAgentSessionServices,
|
|
5157
|
+
createCodemodeExtension,
|
|
5158
|
+
createMcpExtension,
|
|
5159
|
+
createToolSearchExtension,
|
|
5160
|
+
InteractiveMode,
|
|
5161
|
+
SessionManager,
|
|
5162
|
+
SettingsManager
|
|
5163
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5164
|
+
|
|
5090
5165
|
// ../pi-ads/src/api.ts
|
|
5091
5166
|
var REQUEST_TIMEOUT_MS = 5000;
|
|
5092
5167
|
async function authedFetch(deps, path, init) {
|
|
@@ -5100,10 +5175,38 @@ async function authedFetch(deps, path, init) {
|
|
|
5100
5175
|
...init?.headers ?? {},
|
|
5101
5176
|
Authorization: `Bearer ${token}`,
|
|
5102
5177
|
"Content-Type": "application/json",
|
|
5103
|
-
...deps.sessionId && (path.startsWith("/ads/next") || path === "/ads/impression") ? { "x-session-id": deps.sessionId } : {}
|
|
5178
|
+
...deps.sessionId && (path.startsWith("/ads/next") || path === "/ads/impression") ? { "x-session-id": deps.sessionId } : {},
|
|
5179
|
+
...path.startsWith("/ads/next") ? gravityHeader(deps) : {}
|
|
5104
5180
|
}
|
|
5105
5181
|
});
|
|
5106
5182
|
}
|
|
5183
|
+
function gravityHeader(deps) {
|
|
5184
|
+
try {
|
|
5185
|
+
const ctx = deps.getGravityContext?.();
|
|
5186
|
+
return ctx ? { [GRAVITY_CONTEXT_HEADER]: ctx } : {};
|
|
5187
|
+
} catch {
|
|
5188
|
+
return {};
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
var IMP_TIMEOUT_MS = 3000;
|
|
5192
|
+
function isGravityImpUrl(raw) {
|
|
5193
|
+
if (!raw)
|
|
5194
|
+
return false;
|
|
5195
|
+
try {
|
|
5196
|
+
const u = new URL(raw);
|
|
5197
|
+
return u.protocol === "https:" && /(^|\.)trygravity\.(ai|com)$/.test(u.hostname);
|
|
5198
|
+
} catch {
|
|
5199
|
+
return false;
|
|
5200
|
+
}
|
|
5201
|
+
}
|
|
5202
|
+
function fireGravityImpression(deps, ad) {
|
|
5203
|
+
if (ad.source !== "gravity" || !isGravityImpUrl(ad.imp_url))
|
|
5204
|
+
return false;
|
|
5205
|
+
try {
|
|
5206
|
+
Promise.resolve((deps.fetchImpl ?? fetch)(ad.imp_url, { method: "GET", signal: AbortSignal.timeout(IMP_TIMEOUT_MS) })).catch(() => {});
|
|
5207
|
+
} catch {}
|
|
5208
|
+
return true;
|
|
5209
|
+
}
|
|
5107
5210
|
async function fetchAdNext(deps, slot) {
|
|
5108
5211
|
try {
|
|
5109
5212
|
const res = await authedFetch(deps, `/ads/next?slot=${slot}`);
|
|
@@ -5114,11 +5217,11 @@ async function fetchAdNext(deps, slot) {
|
|
|
5114
5217
|
return;
|
|
5115
5218
|
}
|
|
5116
5219
|
}
|
|
5117
|
-
async function postImpression(deps, adId, clickToken) {
|
|
5220
|
+
async function postImpression(deps, adId, clickToken, impFired = false) {
|
|
5118
5221
|
try {
|
|
5119
5222
|
await authedFetch(deps, "/ads/impression", {
|
|
5120
5223
|
method: "POST",
|
|
5121
|
-
body: JSON.stringify({ ad_id: adId, click_token: clickToken })
|
|
5224
|
+
body: JSON.stringify({ ad_id: adId, click_token: clickToken, ...impFired ? { imp_fired: true } : {} })
|
|
5122
5225
|
});
|
|
5123
5226
|
} catch {}
|
|
5124
5227
|
}
|
|
@@ -5134,7 +5237,7 @@ async function fetchMe(deps) {
|
|
|
5134
5237
|
}
|
|
5135
5238
|
|
|
5136
5239
|
// ../pi-ads/src/style.ts
|
|
5137
|
-
import { createHash } from "node:crypto";
|
|
5240
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
5138
5241
|
var OSC_RE = /\x1b\][\s\S]*?(?:\x07|\x1b\\)/g;
|
|
5139
5242
|
var CSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
5140
5243
|
var C1_RE = /[\x80-\x9f]/g;
|
|
@@ -5167,7 +5270,7 @@ function renderAdCard(creative, clickUrl, theme, columns) {
|
|
|
5167
5270
|
const label = " AD ░▒▓ ";
|
|
5168
5271
|
const top = `┌${label}${"─".repeat(Math.max(0, innerWidth + 2 - label.length))}┐`;
|
|
5169
5272
|
const bottom = `└${"─".repeat(innerWidth + 2)}┘`;
|
|
5170
|
-
const linkId =
|
|
5273
|
+
const linkId = createHash2("sha256").update(url).digest("hex").slice(0, 12);
|
|
5171
5274
|
const row = (text, opts) => {
|
|
5172
5275
|
const plain = pad(truncate(text, innerWidth), innerWidth);
|
|
5173
5276
|
let styled = theme.fg("accent", plain);
|
|
@@ -5201,16 +5304,33 @@ function renderWarningLine(message, theme) {
|
|
|
5201
5304
|
var BANNER_WIDGET_ID = "freepi-ad";
|
|
5202
5305
|
function createBannerRenderer(opts = {}) {
|
|
5203
5306
|
let lastPostedToken;
|
|
5307
|
+
const screen = opts.screen ?? {};
|
|
5204
5308
|
return {
|
|
5205
5309
|
async render(deps, ctx, config, columnsOverride) {
|
|
5206
5310
|
const ad = await fetchAdNext(deps, "banner");
|
|
5207
5311
|
if (opts.isActive && !opts.isActive())
|
|
5208
5312
|
return;
|
|
5209
5313
|
if (!ad) {
|
|
5314
|
+
screen.banner = undefined;
|
|
5210
5315
|
ctx.ui.setWidget(BANNER_WIDGET_ID, undefined);
|
|
5211
5316
|
opts.onBannerAd?.(undefined);
|
|
5212
5317
|
return;
|
|
5213
5318
|
}
|
|
5319
|
+
const isGravity = ad.source === "gravity";
|
|
5320
|
+
if (screen.inline === "gravity") {
|
|
5321
|
+
screen.banner = undefined;
|
|
5322
|
+
ctx.ui.setWidget(BANNER_WIDGET_ID, undefined);
|
|
5323
|
+
opts.onBannerAd?.(undefined);
|
|
5324
|
+
return;
|
|
5325
|
+
}
|
|
5326
|
+
if (isGravity && screen.inline)
|
|
5327
|
+
screen.clearInline?.();
|
|
5328
|
+
screen.banner = isGravity ? "gravity" : "own";
|
|
5329
|
+
screen.clearBanner = () => {
|
|
5330
|
+
screen.banner = undefined;
|
|
5331
|
+
ctx.ui.setWidget(BANNER_WIDGET_ID, undefined);
|
|
5332
|
+
opts.onBannerAd?.(undefined);
|
|
5333
|
+
};
|
|
5214
5334
|
const theme = ctx.ui.theme;
|
|
5215
5335
|
const columns = columnsOverride ?? process.stdout.columns ?? 80;
|
|
5216
5336
|
const lines = columns >= config.adMinColumns ? renderAdCard(ad.creative, ad.click_url, theme, columns) : [renderPlainAdLine(ad.creative, ad.click_url, theme, columns)];
|
|
@@ -5218,7 +5338,8 @@ function createBannerRenderer(opts = {}) {
|
|
|
5218
5338
|
opts.onBannerAd?.(ad.click_url);
|
|
5219
5339
|
if (lastPostedToken !== ad.click_token) {
|
|
5220
5340
|
lastPostedToken = ad.click_token;
|
|
5221
|
-
|
|
5341
|
+
const impFired = fireGravityImpression(deps, ad);
|
|
5342
|
+
await postImpression(deps, ad.ad_id, ad.click_token, impFired);
|
|
5222
5343
|
}
|
|
5223
5344
|
}
|
|
5224
5345
|
};
|
|
@@ -5226,37 +5347,48 @@ function createBannerRenderer(opts = {}) {
|
|
|
5226
5347
|
|
|
5227
5348
|
// ../pi-ads/src/inline.ts
|
|
5228
5349
|
var INLINE_WIDGET_ID = "freepi-ad-inline";
|
|
5229
|
-
function createInlineRenderer() {
|
|
5350
|
+
function createInlineRenderer(screen = {}) {
|
|
5230
5351
|
let turnCount = 0;
|
|
5231
5352
|
let inlineVisible = false;
|
|
5232
5353
|
let lastPostedToken;
|
|
5354
|
+
const clearInline = (ctx) => {
|
|
5355
|
+
if (inlineVisible)
|
|
5356
|
+
ctx.ui.setWidget(INLINE_WIDGET_ID, undefined);
|
|
5357
|
+
inlineVisible = false;
|
|
5358
|
+
screen.inline = undefined;
|
|
5359
|
+
};
|
|
5233
5360
|
return {
|
|
5234
5361
|
async onTurnEnd(deps, ctx, config, columnsOverride) {
|
|
5235
5362
|
turnCount += 1;
|
|
5236
|
-
|
|
5237
|
-
ctx.ui.setWidget(INLINE_WIDGET_ID, undefined);
|
|
5238
|
-
inlineVisible = false;
|
|
5239
|
-
}
|
|
5363
|
+
clearInline(ctx);
|
|
5240
5364
|
if (turnCount % config.adInlineTurnFrequency !== 0)
|
|
5241
5365
|
return;
|
|
5366
|
+
if (screen.banner === "gravity")
|
|
5367
|
+
return;
|
|
5242
5368
|
const ad = await fetchAdNext(deps, "inline");
|
|
5243
5369
|
if (!ad)
|
|
5244
5370
|
return;
|
|
5371
|
+
const isGravity = ad.source === "gravity";
|
|
5372
|
+
if (screen.banner === "gravity")
|
|
5373
|
+
return;
|
|
5374
|
+
if (isGravity && screen.banner)
|
|
5375
|
+
screen.clearBanner?.();
|
|
5245
5376
|
const theme = ctx.ui.theme;
|
|
5246
5377
|
const columns = columnsOverride ?? process.stdout.columns ?? 80;
|
|
5247
5378
|
const lines = columns >= config.adMinColumns ? renderAdCard(ad.creative, ad.click_url, theme, columns) : [renderPlainAdLine(ad.creative, ad.click_url, theme, columns)];
|
|
5248
5379
|
ctx.ui.setWidget(INLINE_WIDGET_ID, lines, { placement: "belowEditor" });
|
|
5249
5380
|
inlineVisible = true;
|
|
5381
|
+
screen.inline = isGravity ? "gravity" : "own";
|
|
5382
|
+
screen.clearInline = () => clearInline(ctx);
|
|
5250
5383
|
if (lastPostedToken !== ad.click_token) {
|
|
5251
5384
|
lastPostedToken = ad.click_token;
|
|
5252
|
-
|
|
5385
|
+
const impFired = fireGravityImpression(deps, ad);
|
|
5386
|
+
await postImpression(deps, ad.ad_id, ad.click_token, impFired);
|
|
5253
5387
|
}
|
|
5254
5388
|
},
|
|
5255
5389
|
reset(ctx) {
|
|
5256
5390
|
turnCount = 0;
|
|
5257
|
-
|
|
5258
|
-
ctx.ui.setWidget(INLINE_WIDGET_ID, undefined);
|
|
5259
|
-
inlineVisible = false;
|
|
5391
|
+
clearInline(ctx);
|
|
5260
5392
|
}
|
|
5261
5393
|
};
|
|
5262
5394
|
}
|
|
@@ -5371,15 +5503,17 @@ function createAdsExtension(opts) {
|
|
|
5371
5503
|
baseUrl: opts.baseUrl,
|
|
5372
5504
|
getToken: opts.getToken,
|
|
5373
5505
|
sessionId: opts.sessionId,
|
|
5374
|
-
fetchImpl: opts.fetchImpl
|
|
5506
|
+
fetchImpl: opts.fetchImpl,
|
|
5507
|
+
getGravityContext: opts.getGravityContext
|
|
5375
5508
|
};
|
|
5376
5509
|
const config = loadConfig();
|
|
5377
5510
|
return {
|
|
5378
5511
|
name: "free-pi-ads",
|
|
5379
5512
|
factory(pi) {
|
|
5380
5513
|
let stopped = false;
|
|
5381
|
-
const
|
|
5382
|
-
const
|
|
5514
|
+
const screen = {};
|
|
5515
|
+
const banner = createBannerRenderer({ onBannerAd: opts.onBannerAd, isActive: () => !stopped, screen });
|
|
5516
|
+
const inline = createInlineRenderer(screen);
|
|
5383
5517
|
let bannerInterval;
|
|
5384
5518
|
let lastBannerAt = 0;
|
|
5385
5519
|
let bannerInFlight = false;
|
|
@@ -5453,7 +5587,7 @@ function buildProviderConfig(baseUrl, jwt, sessionId, models) {
|
|
|
5453
5587
|
};
|
|
5454
5588
|
}
|
|
5455
5589
|
|
|
5456
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5590
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/memory/metrics.mjs
|
|
5457
5591
|
var Metrics = {
|
|
5458
5592
|
assign: 0,
|
|
5459
5593
|
create: 0,
|
|
@@ -5461,7 +5595,8 @@ var Metrics = {
|
|
|
5461
5595
|
discard: 0,
|
|
5462
5596
|
update: 0
|
|
5463
5597
|
};
|
|
5464
|
-
|
|
5598
|
+
|
|
5599
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/guard/guard.mjs
|
|
5465
5600
|
function IsArray(value) {
|
|
5466
5601
|
return Array.isArray(value);
|
|
5467
5602
|
}
|
|
@@ -5506,7 +5641,7 @@ function Keys(value) {
|
|
|
5506
5641
|
function Symbols(value) {
|
|
5507
5642
|
return Object.getOwnPropertySymbols(value);
|
|
5508
5643
|
}
|
|
5509
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5644
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/guard/globals.mjs
|
|
5510
5645
|
function IsTypeArray(value) {
|
|
5511
5646
|
return globalThis.ArrayBuffer.isView(value);
|
|
5512
5647
|
}
|
|
@@ -5519,7 +5654,25 @@ function IsSet(value) {
|
|
|
5519
5654
|
function IsMap(value) {
|
|
5520
5655
|
return value instanceof globalThis.Map;
|
|
5521
5656
|
}
|
|
5522
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5657
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/settings/settings.mjs
|
|
5658
|
+
var settings = {
|
|
5659
|
+
immutableTypes: false,
|
|
5660
|
+
maxErrors: 8,
|
|
5661
|
+
maxInstantiationCount: 128,
|
|
5662
|
+
useAcceleration: true,
|
|
5663
|
+
exactOptionalPropertyTypes: false,
|
|
5664
|
+
enumerableKind: false,
|
|
5665
|
+
correctiveParse: false,
|
|
5666
|
+
unionPrioritySort: true
|
|
5667
|
+
};
|
|
5668
|
+
function Get() {
|
|
5669
|
+
return settings;
|
|
5670
|
+
}
|
|
5671
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/memory/freeze.mjs
|
|
5672
|
+
function Freeze(value) {
|
|
5673
|
+
return Get().immutableTypes ? Object.freeze(value) : value;
|
|
5674
|
+
}
|
|
5675
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/memory/clone.mjs
|
|
5523
5676
|
function FromClassInstance(value) {
|
|
5524
5677
|
return value;
|
|
5525
5678
|
}
|
|
@@ -5578,21 +5731,7 @@ function Clone(value) {
|
|
|
5578
5731
|
Metrics.clone += 1;
|
|
5579
5732
|
return FromValue(value);
|
|
5580
5733
|
}
|
|
5581
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5582
|
-
var settings = {
|
|
5583
|
-
immutableTypes: false,
|
|
5584
|
-
maxErrors: 8,
|
|
5585
|
-
maxInstantiationCount: 128,
|
|
5586
|
-
useAcceleration: true,
|
|
5587
|
-
exactOptionalPropertyTypes: false,
|
|
5588
|
-
enumerableKind: false,
|
|
5589
|
-
correctiveParse: false,
|
|
5590
|
-
unionPrioritySort: true
|
|
5591
|
-
};
|
|
5592
|
-
function Get() {
|
|
5593
|
-
return settings;
|
|
5594
|
-
}
|
|
5595
|
-
// ../../node_modules/.bun/typebox@1.3.16/node_modules/typebox/build/system/memory/create.mjs
|
|
5734
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/memory/create.mjs
|
|
5596
5735
|
function MergeHidden(left, right) {
|
|
5597
5736
|
for (const key of Object.keys(right)) {
|
|
5598
5737
|
Object.defineProperty(left, key, {
|
|
@@ -5609,12 +5748,11 @@ function Merge(left, right) {
|
|
|
5609
5748
|
}
|
|
5610
5749
|
function Create(hidden, enumerable, options = {}) {
|
|
5611
5750
|
Metrics.create += 1;
|
|
5612
|
-
const settings = Get();
|
|
5613
5751
|
const withOptions = Merge(enumerable, options);
|
|
5614
|
-
const withHidden =
|
|
5615
|
-
return
|
|
5752
|
+
const withHidden = Get().enumerableKind ? Merge(withOptions, hidden) : MergeHidden(withOptions, hidden);
|
|
5753
|
+
return Freeze(withHidden);
|
|
5616
5754
|
}
|
|
5617
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5755
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/memory/update.mjs
|
|
5618
5756
|
function Update(current, hidden, enumerable) {
|
|
5619
5757
|
Metrics.update += 1;
|
|
5620
5758
|
const settings = Get();
|
|
@@ -5635,14 +5773,14 @@ function Update(current, hidden, enumerable) {
|
|
|
5635
5773
|
value: enumerable[key]
|
|
5636
5774
|
});
|
|
5637
5775
|
}
|
|
5638
|
-
return result;
|
|
5776
|
+
return Freeze(result);
|
|
5639
5777
|
}
|
|
5640
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5778
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/schema.mjs
|
|
5641
5779
|
function IsSchema(value) {
|
|
5642
5780
|
return IsObject(value);
|
|
5643
5781
|
}
|
|
5644
5782
|
|
|
5645
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5783
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/optional/instantiate_add.mjs
|
|
5646
5784
|
function AddOptionalOperation(type) {
|
|
5647
5785
|
return Update(type, { "~optional": true }, {});
|
|
5648
5786
|
}
|
|
@@ -5651,12 +5789,12 @@ function AddOptionalAction(type, options) {
|
|
|
5651
5789
|
return result;
|
|
5652
5790
|
}
|
|
5653
5791
|
|
|
5654
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5792
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/action/_add_optional.mjs
|
|
5655
5793
|
function AddOptional(type, options = {}) {
|
|
5656
5794
|
return AddOptionalAction(type, options);
|
|
5657
5795
|
}
|
|
5658
5796
|
|
|
5659
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5797
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/_optional.mjs
|
|
5660
5798
|
function Optional(type) {
|
|
5661
5799
|
return AddOptional(type);
|
|
5662
5800
|
}
|
|
@@ -5664,18 +5802,18 @@ function IsOptional(value) {
|
|
|
5664
5802
|
return IsSchema(value) && HasPropertyKey(value, "~optional");
|
|
5665
5803
|
}
|
|
5666
5804
|
|
|
5667
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5805
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/properties.mjs
|
|
5668
5806
|
function RequiredArray(properties) {
|
|
5669
5807
|
return Keys(properties).filter((key) => !IsOptional(properties[key]));
|
|
5670
5808
|
}
|
|
5671
5809
|
|
|
5672
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5810
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/object.mjs
|
|
5673
5811
|
function _Object_(properties, options = {}) {
|
|
5674
5812
|
const requiredKeys = RequiredArray(properties);
|
|
5675
5813
|
const required = requiredKeys.length > 0 ? { required: requiredKeys } : {};
|
|
5676
5814
|
return Create({ "~kind": "Object" }, { type: "object", ...required, properties }, options);
|
|
5677
5815
|
}
|
|
5678
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5816
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/system/hashing/hash.mjs
|
|
5679
5817
|
var ByteMarker;
|
|
5680
5818
|
(function(ByteMarker) {
|
|
5681
5819
|
ByteMarker[ByteMarker["Array"] = 0] = "Array";
|
|
@@ -5700,9 +5838,9 @@ var F64 = new Float64Array(1);
|
|
|
5700
5838
|
var F64In = new DataView(F64.buffer);
|
|
5701
5839
|
var F64Out = new Uint8Array(F64.buffer);
|
|
5702
5840
|
var encoder = new TextEncoder;
|
|
5703
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5841
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/integer.mjs
|
|
5704
5842
|
var IntegerPattern = "-?(?:0|[1-9][0-9]*)";
|
|
5705
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5843
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/literal.mjs
|
|
5706
5844
|
class InvalidLiteralValue extends Error {
|
|
5707
5845
|
constructor(value) {
|
|
5708
5846
|
super(`Invalid Literal value`);
|
|
@@ -5722,27 +5860,27 @@ function LiteralTypeName(value) {
|
|
|
5722
5860
|
function Literal(value, options) {
|
|
5723
5861
|
return Create({ "~kind": "Literal" }, { type: LiteralTypeName(value), const: value }, options);
|
|
5724
5862
|
}
|
|
5725
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5863
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/number.mjs
|
|
5726
5864
|
var NumberPattern = "-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?";
|
|
5727
5865
|
function Number2(options) {
|
|
5728
5866
|
return Create({ "~kind": "Number" }, { type: "number" }, options);
|
|
5729
5867
|
}
|
|
5730
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5868
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/string.mjs
|
|
5731
5869
|
var StringPattern = ".*";
|
|
5732
5870
|
function String2(options) {
|
|
5733
5871
|
return Create({ "~kind": "String" }, { type: "string" }, options);
|
|
5734
5872
|
}
|
|
5735
5873
|
|
|
5736
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5874
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/union.mjs
|
|
5737
5875
|
function Union(anyOf, options = {}) {
|
|
5738
5876
|
return Create({ "~kind": "Union" }, { anyOf }, options);
|
|
5739
5877
|
}
|
|
5740
5878
|
|
|
5741
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5879
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/record.mjs
|
|
5742
5880
|
var IntegerKey = `^${IntegerPattern}$`;
|
|
5743
5881
|
var NumberKey = `^${NumberPattern}$`;
|
|
5744
5882
|
var StringKey = `^${StringPattern}$`;
|
|
5745
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5883
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/internal/char.mjs
|
|
5746
5884
|
function Range(start, end) {
|
|
5747
5885
|
return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
|
|
5748
5886
|
}
|
|
@@ -5756,17 +5894,17 @@ var Digit = [Zero, ...NonZero];
|
|
|
5756
5894
|
var UnderScore = "_";
|
|
5757
5895
|
var DollarSign = "$";
|
|
5758
5896
|
|
|
5759
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5897
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_integer.mjs
|
|
5760
5898
|
var AllowedDigits = [...Digit, UnderScore];
|
|
5761
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5899
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/ident.mjs
|
|
5762
5900
|
var Initial = [...Alpha, UnderScore, DollarSign];
|
|
5763
5901
|
var Remaining = [...Initial, ...Digit];
|
|
5764
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5902
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_number.mjs
|
|
5765
5903
|
var AllowedDigits2 = [...Digit, UnderScore];
|
|
5766
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5904
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/helpers/keys.mjs
|
|
5767
5905
|
var integerKeyPattern = new RegExp("^(?:0|[1-9][0-9]*)$");
|
|
5768
5906
|
|
|
5769
|
-
// ../../node_modules/.bun/typebox@1.3.
|
|
5907
|
+
// ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/indexed/from_object.mjs
|
|
5770
5908
|
var NumericKeyPattern = new RegExp(IntegerKey);
|
|
5771
5909
|
// src/usage-tool.ts
|
|
5772
5910
|
var USAGE_TOOL_NAME = "free_pi_usage";
|
|
@@ -6464,6 +6602,19 @@ function installFooterRightAlign(mode) {
|
|
|
6464
6602
|
|
|
6465
6603
|
// src/changelog.ts
|
|
6466
6604
|
var CHANGELOG_HIGHLIGHTS = [
|
|
6605
|
+
{
|
|
6606
|
+
version: "0.4.5",
|
|
6607
|
+
highlights: [
|
|
6608
|
+
"New /reverse-engineer-anything command: loads REA reverse-engineering tools (apps, binaries, APKs, websites) into the session. For lawful, authorized analysis only."
|
|
6609
|
+
]
|
|
6610
|
+
},
|
|
6611
|
+
{
|
|
6612
|
+
version: "0.4.4",
|
|
6613
|
+
highlights: [
|
|
6614
|
+
"Updated terms: you'll be asked to accept them once.",
|
|
6615
|
+
"Some ads now come from Gravity, measured with a small tracker. Turn it off with FREEPI_NO_GRAVITY_PIXEL=1."
|
|
6616
|
+
]
|
|
6617
|
+
},
|
|
6467
6618
|
{
|
|
6468
6619
|
version: "0.4.3",
|
|
6469
6620
|
highlights: [
|
|
@@ -6703,6 +6854,33 @@ async function showUsage(opts, ctx) {
|
|
|
6703
6854
|
const r = await fetchUsageText(opts);
|
|
6704
6855
|
ctx.ui.notify(r.text, r.ok ? "info" : "error");
|
|
6705
6856
|
}
|
|
6857
|
+
var REA_ARGS = ["-y", "rea-agents@6.7.0", "mcp"];
|
|
6858
|
+
var REA_DESCRIPTION = "Reverse-engineering tools (REA): native binaries, JS/Electron apps, APKs, .NET, websites. Use for lawful, authorized analysis only.";
|
|
6859
|
+
var REA_NODE_RANGE = "^22.19.0, ^24.11.0, or >=26.0.0";
|
|
6860
|
+
function reaSupportsNode(version) {
|
|
6861
|
+
const [major = 0, minor = 0] = version.split(".").map(Number);
|
|
6862
|
+
return major >= 26 || major === 24 && minor >= 11 || major === 22 && minor >= 19;
|
|
6863
|
+
}
|
|
6864
|
+
function loadRea(pi, opts, ctx) {
|
|
6865
|
+
const nodeVersion = opts.nodeVersion ?? process.versions.node;
|
|
6866
|
+
if (!reaSupportsNode(nodeVersion)) {
|
|
6867
|
+
ctx.ui.notify(`REA needs Node ${REA_NODE_RANGE}; you are on Node ${nodeVersion}. Update Node and restart free-pi-cli.`, "error");
|
|
6868
|
+
return;
|
|
6869
|
+
}
|
|
6870
|
+
if (pi.getMcpServers().some((s) => s.name === "rea")) {
|
|
6871
|
+
ctx.ui.notify("REA is already loaded in this session.", "info");
|
|
6872
|
+
return;
|
|
6873
|
+
}
|
|
6874
|
+
const win = (opts.platform ?? process.platform) === "win32";
|
|
6875
|
+
const server = opts.reaServer ?? (win ? { command: "cmd.exe", args: ["/d", "/c", "npx", ...REA_ARGS] } : { command: "npx", args: REA_ARGS });
|
|
6876
|
+
try {
|
|
6877
|
+
pi.registerMcpServer("rea", { ...server, exposure: "codemode", description: REA_DESCRIPTION, timeout: 300 });
|
|
6878
|
+
} catch {
|
|
6879
|
+
ctx.ui.notify("Couldn't load REA in this session.", "error");
|
|
6880
|
+
return;
|
|
6881
|
+
}
|
|
6882
|
+
ctx.ui.notify("Loading REA (reverse-engineering tools) for this session. The first run downloads rea-agents, so it can take a minute. Deep native analysis needs your own Hopper, Ghidra, or IDA install.", "info");
|
|
6883
|
+
}
|
|
6706
6884
|
function createFreePiCommandsExtension(opts) {
|
|
6707
6885
|
return {
|
|
6708
6886
|
name: "free-pi-commands",
|
|
@@ -6740,6 +6918,10 @@ function createFreePiCommandsExtension(opts) {
|
|
|
6740
6918
|
description: "Open the free-pi Privacy Policy in your browser.",
|
|
6741
6919
|
handler: (_args, ctx) => openPrivacyPolicy(opts, ctx)
|
|
6742
6920
|
});
|
|
6921
|
+
pi.registerCommand("reverse-engineer-anything", {
|
|
6922
|
+
description: "Load reverse-engineering tools (REA: binaries, apps, APKs, websites) for this session.",
|
|
6923
|
+
handler: async (_args, ctx) => loadRea(pi, opts, ctx)
|
|
6924
|
+
});
|
|
6743
6925
|
}
|
|
6744
6926
|
};
|
|
6745
6927
|
}
|
|
@@ -7044,6 +7226,7 @@ function buildRuntimeOptions(opts, sessionId) {
|
|
|
7044
7226
|
baseUrl: opts.baseUrl,
|
|
7045
7227
|
getToken: () => opts.jwt,
|
|
7046
7228
|
sessionId,
|
|
7229
|
+
getGravityContext: opts.getGravityContext,
|
|
7047
7230
|
onBannerAd: (u) => {
|
|
7048
7231
|
advertiserUrl = u;
|
|
7049
7232
|
}
|
|
@@ -7184,6 +7367,9 @@ free-pi — before you start
|
|
|
7184
7367
|
* Ad cards render in the terminal UI. Some ads come from a third-party ad
|
|
7185
7368
|
provider (Gravity), which receives excerpts of your recent conversation
|
|
7186
7369
|
to pick a relevant ad.
|
|
7370
|
+
* Gravity also keeps a session and visitor ID on your machine (in
|
|
7371
|
+
~/.free-pi) and receives usage events from free-pi to measure and
|
|
7372
|
+
attribute ads.
|
|
7187
7373
|
* Your coding sessions (prompts, code, files, and model responses) are saved
|
|
7188
7374
|
as traces and used to train models. We may share or sell that data to
|
|
7189
7375
|
third parties. Once you accept, there is no opt-out, except where the law
|
|
@@ -7202,7 +7388,7 @@ and the Privacy Policy (https://freepi.ai/privacy).
|
|
|
7202
7388
|
|
|
7203
7389
|
Decline and nothing is sent to the free-pi server.
|
|
7204
7390
|
`.trim();
|
|
7205
|
-
var CONSENT_VERSION = "
|
|
7391
|
+
var CONSENT_VERSION = "4";
|
|
7206
7392
|
var NON_INTERACTIVE_CONSENT_TEXT = "free-pi first-run consent needs an interactive terminal (stdin is not a TTY). " + "Run `npx free-pi-cli` in a terminal once to review and accept; " + "after that, non-interactive runs work.";
|
|
7207
7393
|
var CONSENT_PROMPT = "Accept? [y/N] ";
|
|
7208
7394
|
function parseConsentAnswer(answer) {
|
|
@@ -7437,14 +7623,17 @@ async function run(deps, argv = process.argv) {
|
|
|
7437
7623
|
return 1;
|
|
7438
7624
|
}
|
|
7439
7625
|
let jwt = await loadJwt(deps.credentialsPath);
|
|
7626
|
+
let consentCurrent = false;
|
|
7440
7627
|
if (jwt) {
|
|
7441
7628
|
try {
|
|
7442
7629
|
const serverConsent = await checkToken(deps.baseUrl, jwt);
|
|
7630
|
+
consentCurrent = serverConsent === CONSENT_VERSION;
|
|
7443
7631
|
if (serverConsent !== undefined && serverConsent !== CONSENT_VERSION) {
|
|
7444
7632
|
if (!await deps.promptConsent(REPROMPT_CONSENT_TEXT)) {
|
|
7445
7633
|
deps.log("Declined. free-pi needs you to accept the updated terms to continue; you will be asked again next time.");
|
|
7446
7634
|
return 1;
|
|
7447
7635
|
}
|
|
7636
|
+
consentCurrent = true;
|
|
7448
7637
|
try {
|
|
7449
7638
|
await submitUserConsent(deps.baseUrl, jwt, CONSENT_VERSION);
|
|
7450
7639
|
} catch (err) {
|
|
@@ -7467,6 +7656,7 @@ async function run(deps, argv = process.argv) {
|
|
|
7467
7656
|
}
|
|
7468
7657
|
showIntro(deps.log);
|
|
7469
7658
|
jwt = await loginFlow(deps);
|
|
7659
|
+
consentCurrent = true;
|
|
7470
7660
|
}
|
|
7471
7661
|
const versionCheck = await deps.checkClientVersion(deps.baseUrl, CLI_VERSION);
|
|
7472
7662
|
let updateLatest;
|
|
@@ -7487,6 +7677,12 @@ async function run(deps, argv = process.argv) {
|
|
|
7487
7677
|
deps.log(whatsNew);
|
|
7488
7678
|
if (versionCheck.notice)
|
|
7489
7679
|
deps.log(versionCheck.notice);
|
|
7680
|
+
let getGravityContext;
|
|
7681
|
+
if (consentCurrent) {
|
|
7682
|
+
try {
|
|
7683
|
+
getGravityContext = deps.startGravityPixel?.(jwt);
|
|
7684
|
+
} catch {}
|
|
7685
|
+
}
|
|
7490
7686
|
const finalSessionId = await deps.launchPi({
|
|
7491
7687
|
baseUrl: deps.baseUrl,
|
|
7492
7688
|
jwt,
|
|
@@ -7494,7 +7690,8 @@ async function run(deps, argv = process.argv) {
|
|
|
7494
7690
|
session: sessionArg.session,
|
|
7495
7691
|
model: versionCheck.model,
|
|
7496
7692
|
models: versionCheck.models,
|
|
7497
|
-
updateLatest
|
|
7693
|
+
updateLatest,
|
|
7694
|
+
getGravityContext
|
|
7498
7695
|
});
|
|
7499
7696
|
deps.log(finalSessionId ? `
|
|
7500
7697
|
free-pi session ended. Start it again anytime: npx free-pi-cli --session ${finalSessionId}` : `
|
|
@@ -7620,6 +7817,7 @@ ${HELP_TEXT}`);
|
|
|
7620
7817
|
launchPi,
|
|
7621
7818
|
log: (message) => console.log(message),
|
|
7622
7819
|
checkClientVersion,
|
|
7820
|
+
startGravityPixel: (jwt) => startGravityPixel(jwt, join5(dirname5(agentDir), "gravity")),
|
|
7623
7821
|
maybeSelfUpdate: (action, latest) => maybeSelfUpdate(action, latest, {
|
|
7624
7822
|
env: process.env,
|
|
7625
7823
|
autoUpdateEnabled: () => readAutoUpdate(getConfigPath()),
|