@pasko70/pibo 1.6.0 → 1.7.1
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/apps/chat/chat-trace-helpers.js +47 -4
- package/dist/apps/chat/trace-v2.js +302 -0
- package/dist/apps/chat/trace.js +31 -2
- package/dist/apps/chat/web-app.js +371 -10
- package/dist/apps/chat-ui/assets/{dist-aLS3alom.js → dist-B7ZRIJ16.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-DYqJWYtm.js → dist-BDNjNt4b.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D87he9he.js → dist-BDxKfyTI.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-B0i7AU1O.js → dist-CA1Gi-1G.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BwZj_mI4.js → dist-CTQ40XYd.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-wyhLeLW6.js → dist-CcwGcMtk.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CFoGUjhX.js → dist-D8Q2E5o5.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dm6UhVM6.js → dist-DJJN6SPt.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BbCXk-v9.js → dist-exkn8clz.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Yx8i6oQ1.js → dist-mG9WxdYM.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-C-UobPQQ.js → dist-r34sHBLi.js} +1 -1
- package/dist/apps/chat-ui/assets/index-C5smwAJD.js +166 -0
- package/dist/apps/chat-ui/assets/index-D8itqvK_.css +1 -0
- package/dist/apps/chat-ui/index.html +2 -2
- package/dist/apps/chat-ui/sw.js +7 -1
- package/dist/apps/chat-vscode-web/assets/index-lOZ1r-No.js +41 -0
- package/dist/apps/chat-vscode-web/index.html +1 -1
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.7.1.vsix +0 -0
- package/dist/cli.js +10 -0
- package/dist/data/payload-store.js +18 -9
- package/dist/gateway/cli.js +108 -6
- package/dist/gateway/web.js +2 -0
- package/dist/session-ui/terminalRows.js +5 -0
- package/dist/web/http.js +17 -6
- package/package.json +93 -93
- package/dist/apps/chat-ui/assets/index-CNDX-4Kp.js +0 -166
- package/dist/apps/chat-ui/assets/index-DvBWSeIO.css +0 -1
- package/dist/apps/chat-vscode-web/assets/index-lA76A7Pc.js +0 -41
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.6.0.vsix +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta name="theme-color" content="#101d22" />
|
|
7
7
|
<title>Pibo</title>
|
|
8
|
-
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/apps/chat-vscode/assets/index-lOZ1r-No.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/apps/chat-vscode/assets/index-B5QK07zO.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
Binary file
|
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -365,6 +365,7 @@ export async function runPiboCli(argv = process.argv) {
|
|
|
365
365
|
.option("--web-port <port>", "Bind the HTTP web host port", parsePort)
|
|
366
366
|
.option("--gateway-port <port>", "Bind the agent-runtime gateway port", parsePort)
|
|
367
367
|
.action(async (options) => {
|
|
368
|
+
warnIfUnsupportedGatewayNodeVersion();
|
|
368
369
|
const { runWebGatewayServer } = await import("./gateway/web.js");
|
|
369
370
|
const authMode = options.auth;
|
|
370
371
|
if (authMode !== undefined && authMode !== "better-auth" && authMode !== "local") {
|
|
@@ -397,6 +398,15 @@ export async function runPiboCli(argv = process.argv) {
|
|
|
397
398
|
}
|
|
398
399
|
await program.parseAsync(argv);
|
|
399
400
|
}
|
|
401
|
+
function warnIfUnsupportedGatewayNodeVersion() {
|
|
402
|
+
const major = Number(process.versions.node.split(".")[0]);
|
|
403
|
+
if (Number.isFinite(major) && major >= 24)
|
|
404
|
+
return;
|
|
405
|
+
const message = `Pibo gateway:web requires Node >=24; current runtime is ${process.version}. Upgrade Node before production gateway use.`;
|
|
406
|
+
if (process.env.PIBO_STRICT_NODE_ENGINE === "1")
|
|
407
|
+
throw new Error(message);
|
|
408
|
+
console.warn(`[pibo] warning: ${message}`);
|
|
409
|
+
}
|
|
400
410
|
function printRootDiscoveryText() {
|
|
401
411
|
return `pibo - agent-oriented CLI
|
|
402
412
|
|
|
@@ -3,6 +3,7 @@ import { gunzipSync, gzipSync } from "node:zlib";
|
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, extname, join, resolve } from "node:path";
|
|
5
5
|
import { piboHomePath } from "../core/pibo-home.js";
|
|
6
|
+
const MAX_SYNC_PAYLOAD_GZIP_BYTES = 512 * 1024;
|
|
6
7
|
export class PayloadStore {
|
|
7
8
|
db;
|
|
8
9
|
rootDir;
|
|
@@ -22,10 +23,13 @@ export class PayloadStore {
|
|
|
22
23
|
this.db.prepare("UPDATE payloads SET ref_count = ref_count + 1 WHERE id = ?").run(existing.id);
|
|
23
24
|
return this.getPayload(existing.id) ?? existing;
|
|
24
25
|
}
|
|
25
|
-
const
|
|
26
|
-
const
|
|
26
|
+
const shouldCompress = bytes.byteLength <= MAX_SYNC_PAYLOAD_GZIP_BYTES;
|
|
27
|
+
const encoding = shouldCompress ? "gzip" : "identity";
|
|
28
|
+
const bytesToStore = shouldCompress ? gzipSync(bytes) : bytes;
|
|
29
|
+
const compressedByteSize = shouldCompress ? bytesToStore.byteLength : null;
|
|
30
|
+
const relativePath = buildRelativePayloadPath(sha256, contentType, encoding);
|
|
27
31
|
const absolutePath = this.rootDir === ":memory:" ? relativePath : join(this.rootDir, relativePath);
|
|
28
|
-
|
|
32
|
+
writePayloadFile(absolutePath, bytesToStore);
|
|
29
33
|
const id = input.id ?? `payload_${randomUUID()}`;
|
|
30
34
|
this.db.prepare(`
|
|
31
35
|
INSERT INTO payloads (
|
|
@@ -44,7 +48,7 @@ export class PayloadStore {
|
|
|
44
48
|
created_at,
|
|
45
49
|
last_verified_at
|
|
46
50
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
47
|
-
`).run(id, sha256, "file", relativePath, contentType,
|
|
51
|
+
`).run(id, sha256, "file", relativePath, contentType, encoding, bytes.byteLength, compressedByteSize, previewTextFromValue(input.value) ?? null, input.retentionClass, 1, "committed", createdAt, createdAt);
|
|
48
52
|
const stored = this.getPayload(id);
|
|
49
53
|
if (!stored)
|
|
50
54
|
throw new Error(`Failed to persist payload \"${id}\"`);
|
|
@@ -62,7 +66,11 @@ export class PayloadStore {
|
|
|
62
66
|
throw new Error(`Payload \"${id}\" has no storage path`);
|
|
63
67
|
const absolutePath = this.rootDir === ":memory:" ? payload.storagePath : join(this.rootDir, payload.storagePath);
|
|
64
68
|
const bytes = readFileSync(absolutePath);
|
|
65
|
-
|
|
69
|
+
if (payload.encoding === "gzip")
|
|
70
|
+
return gunzipSync(bytes);
|
|
71
|
+
if (payload.encoding === "identity")
|
|
72
|
+
return bytes;
|
|
73
|
+
throw new Error(`Unsupported payload encoding \"${payload.encoding}\"`);
|
|
66
74
|
}
|
|
67
75
|
readPayloadText(id) {
|
|
68
76
|
return Buffer.from(this.readPayloadBytes(id)).toString("utf8");
|
|
@@ -98,9 +106,10 @@ function previewTextFromValue(value) {
|
|
|
98
106
|
const normalized = text.replace(/\s+/g, " ").trim();
|
|
99
107
|
return normalized ? normalized.slice(0, 1024) : undefined;
|
|
100
108
|
}
|
|
101
|
-
function buildRelativePayloadPath(sha256, contentType) {
|
|
109
|
+
function buildRelativePayloadPath(sha256, contentType, encoding) {
|
|
102
110
|
const extension = extensionForContentType(contentType);
|
|
103
|
-
|
|
111
|
+
const suffix = encoding === "gzip" ? `${extension}.gz` : extension;
|
|
112
|
+
return join("sha256", sha256.slice(0, 2), sha256.slice(2, 4), `${sha256}.${suffix}`);
|
|
104
113
|
}
|
|
105
114
|
function extensionForContentType(contentType) {
|
|
106
115
|
if (contentType.includes("json"))
|
|
@@ -109,13 +118,13 @@ function extensionForContentType(contentType) {
|
|
|
109
118
|
return "txt";
|
|
110
119
|
return "bin";
|
|
111
120
|
}
|
|
112
|
-
function
|
|
121
|
+
function writePayloadFile(path, bytes) {
|
|
113
122
|
if (existsSync(path))
|
|
114
123
|
return;
|
|
115
124
|
mkdirSync(dirname(path), { recursive: true });
|
|
116
125
|
const tempPath = `${path}.tmp-${randomUUID()}${extname(path)}`;
|
|
117
126
|
try {
|
|
118
|
-
writeFileSync(tempPath,
|
|
127
|
+
writeFileSync(tempPath, bytes);
|
|
119
128
|
if (!existsSync(path))
|
|
120
129
|
renameSync(tempPath, path);
|
|
121
130
|
}
|
package/dist/gateway/cli.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { spawn, execFile } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, openSync, readFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
2
5
|
import { promisify } from "node:util";
|
|
3
6
|
import { createConnection } from "node:net";
|
|
4
7
|
import { DEFAULT_GATEWAY_HOST, DEFAULT_GATEWAY_PORT } from "./protocol.js";
|
|
@@ -54,6 +57,97 @@ function gatewayServiceName(target) {
|
|
|
54
57
|
function gatewayManagerCommand() {
|
|
55
58
|
return process.env.PIBO_GATEWAY_MANAGER_COMMAND || "systemctl";
|
|
56
59
|
}
|
|
60
|
+
function shouldUseWindowsGatewayManager() {
|
|
61
|
+
return process.platform === "win32" && !process.env.PIBO_GATEWAY_MANAGER_COMMAND;
|
|
62
|
+
}
|
|
63
|
+
function managedGatewayHome(target) {
|
|
64
|
+
const fromEnv = target === "web" ? process.env.PIBO_GATEWAY_WEB_HOME : process.env.PIBO_GATEWAY_DEV_HOME;
|
|
65
|
+
return fromEnv || join(homedir(), target === "web" ? ".pibo" : ".pibo-dev");
|
|
66
|
+
}
|
|
67
|
+
function targetGatewayPort(target) {
|
|
68
|
+
const fromEnv = target === "web" ? process.env.PIBO_GATEWAY_WEB_AGENT_PORT : process.env.PIBO_GATEWAY_DEV_AGENT_PORT;
|
|
69
|
+
const parsed = fromEnv ? Number(fromEnv) : NaN;
|
|
70
|
+
if (Number.isInteger(parsed) && parsed > 0 && parsed <= 65535)
|
|
71
|
+
return parsed;
|
|
72
|
+
return target === "web" ? 4789 : 4809;
|
|
73
|
+
}
|
|
74
|
+
function resolveGatewayWebCommand(argv, target) {
|
|
75
|
+
const entry = argv[1] ?? "";
|
|
76
|
+
const args = [
|
|
77
|
+
entry,
|
|
78
|
+
"gateway:web",
|
|
79
|
+
"--auth",
|
|
80
|
+
"local",
|
|
81
|
+
"--web-host",
|
|
82
|
+
"127.0.0.1",
|
|
83
|
+
"--web-port",
|
|
84
|
+
String(targetPort(target)),
|
|
85
|
+
"--gateway-port",
|
|
86
|
+
String(targetGatewayPort(target)),
|
|
87
|
+
];
|
|
88
|
+
return { command: process.execPath, args };
|
|
89
|
+
}
|
|
90
|
+
function managedGatewayPidPath(target) {
|
|
91
|
+
return join(managedGatewayHome(target), "gateway.pid");
|
|
92
|
+
}
|
|
93
|
+
function readManagedGatewayPid(target) {
|
|
94
|
+
try {
|
|
95
|
+
const path = managedGatewayPidPath(target);
|
|
96
|
+
if (!existsSync(path))
|
|
97
|
+
return undefined;
|
|
98
|
+
const pid = Number(readFileSync(path, "utf-8").trim());
|
|
99
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
100
|
+
return undefined;
|
|
101
|
+
try {
|
|
102
|
+
process.kill(pid, 0);
|
|
103
|
+
return pid;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function waitForTargetGatewayDown(target, maxRetries = 40, intervalMs = 250) {
|
|
114
|
+
const port = targetPort(target);
|
|
115
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
116
|
+
if (!(await isPortReachable("127.0.0.1", port, 1000)))
|
|
117
|
+
return true;
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
async function runWindowsGatewayManager(action, target, argv) {
|
|
123
|
+
const home = managedGatewayHome(target);
|
|
124
|
+
mkdirSync(home, { recursive: true });
|
|
125
|
+
if (action === "restart") {
|
|
126
|
+
const pid = readManagedGatewayPid(target);
|
|
127
|
+
if (pid !== undefined) {
|
|
128
|
+
try {
|
|
129
|
+
process.kill(pid, "SIGTERM");
|
|
130
|
+
}
|
|
131
|
+
catch { }
|
|
132
|
+
}
|
|
133
|
+
const down = await waitForTargetGatewayDown(target);
|
|
134
|
+
if (!down)
|
|
135
|
+
throw new Error(`Gateway on port ${targetPort(target)} did not stop in time.`);
|
|
136
|
+
}
|
|
137
|
+
const { command, args } = resolveGatewayWebCommand(argv, target);
|
|
138
|
+
const stdout = openSync(join(home, `gateway-${target}-stdout.log`), "a");
|
|
139
|
+
const stderr = openSync(join(home, `gateway-${target}-stderr.log`), "a");
|
|
140
|
+
const child = spawn(command, args, {
|
|
141
|
+
detached: true,
|
|
142
|
+
stdio: ["ignore", stdout, stderr],
|
|
143
|
+
env: {
|
|
144
|
+
...process.env,
|
|
145
|
+
PIBO_HOME: home,
|
|
146
|
+
PIBO_GATEWAY_MODE: expectedMode(target),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
child.unref();
|
|
150
|
+
}
|
|
57
151
|
async function fetchJson(url) {
|
|
58
152
|
const response = await fetch(url, { signal: AbortSignal.timeout(3000) });
|
|
59
153
|
if (!response.ok)
|
|
@@ -175,8 +269,16 @@ function printSafetyStatus(target, status) {
|
|
|
175
269
|
for (const run of status.activeRuns)
|
|
176
270
|
console.log(` ${run.runId ?? "unknown"}: ${run.status ?? "active"}${run.toolName ? ` (${run.toolName})` : ""}`);
|
|
177
271
|
}
|
|
178
|
-
|
|
179
|
-
|
|
272
|
+
function managerRequiresShell(command) {
|
|
273
|
+
return process.platform === "win32" && /\.(?:cmd|bat)$/i.test(command);
|
|
274
|
+
}
|
|
275
|
+
async function runGatewayManager(action, target, argv = process.argv) {
|
|
276
|
+
if (shouldUseWindowsGatewayManager()) {
|
|
277
|
+
await runWindowsGatewayManager(action, target, argv);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const command = gatewayManagerCommand();
|
|
281
|
+
await execFileAsync(command, [action, gatewayServiceName(target)], { timeout: 60000, shell: managerRequiresShell(command) });
|
|
180
282
|
}
|
|
181
283
|
async function waitForManagedGatewayHealth(target) {
|
|
182
284
|
const retries = Number(process.env.PIBO_GATEWAY_HEALTH_RETRIES ?? 30);
|
|
@@ -189,7 +291,7 @@ async function waitForManagedGatewayHealth(target) {
|
|
|
189
291
|
}
|
|
190
292
|
return undefined;
|
|
191
293
|
}
|
|
192
|
-
async function runManagedGatewayCommand(target, command, args) {
|
|
294
|
+
async function runManagedGatewayCommand(target, command, args, argv = process.argv) {
|
|
193
295
|
if (command === "status" || command === "doctor") {
|
|
194
296
|
const status = await readGatewaySafetyStatus(target);
|
|
195
297
|
printSafetyStatus(target, status);
|
|
@@ -222,7 +324,7 @@ async function runManagedGatewayCommand(target, command, args) {
|
|
|
222
324
|
}
|
|
223
325
|
console.error(`Starting ${target === "web" ? "production" : "dev"} gateway...`);
|
|
224
326
|
try {
|
|
225
|
-
await runGatewayManager("start", target);
|
|
327
|
+
await runGatewayManager("start", target, argv);
|
|
226
328
|
}
|
|
227
329
|
catch (error) {
|
|
228
330
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -262,7 +364,7 @@ async function runManagedGatewayCommand(target, command, args) {
|
|
|
262
364
|
}
|
|
263
365
|
console.error(`Restarting ${target === "web" ? "production" : "dev"} gateway...`);
|
|
264
366
|
try {
|
|
265
|
-
await runGatewayManager("restart", target);
|
|
367
|
+
await runGatewayManager("restart", target, argv);
|
|
266
368
|
}
|
|
267
369
|
catch (error) {
|
|
268
370
|
console.error(error instanceof Error ? error.message : String(error));
|
|
@@ -286,7 +388,7 @@ export async function runGatewayCli(argv = process.argv) {
|
|
|
286
388
|
const subcommand = args[1];
|
|
287
389
|
const hasForceFlag = args.includes("--force");
|
|
288
390
|
if (subcommand === "web" || subcommand === "dev") {
|
|
289
|
-
const handled = await runManagedGatewayCommand(subcommand, args[2], args.slice(3));
|
|
391
|
+
const handled = await runManagedGatewayCommand(subcommand, args[2], args.slice(3), argv);
|
|
290
392
|
if (!handled) {
|
|
291
393
|
console.error(`Unknown gateway ${subcommand} subcommand: ${args[2] ?? ""}`);
|
|
292
394
|
printGatewayHelp();
|
package/dist/gateway/web.js
CHANGED
|
@@ -102,6 +102,8 @@ export function resolveWebGatewayServerOptions(options = {}) {
|
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
104
|
function webGatewayMode(options, useDevAuth) {
|
|
105
|
+
if (process.env.PIBO_GATEWAY_MODE === "dev" || process.env.PIBO_GATEWAY_MODE === "prod")
|
|
106
|
+
return process.env.PIBO_GATEWAY_MODE;
|
|
105
107
|
if (useDevAuth)
|
|
106
108
|
return "dev";
|
|
107
109
|
if (options.web?.port === 4808)
|
|
@@ -78,6 +78,7 @@ function debugFields(node) {
|
|
|
78
78
|
orderSource: node.source,
|
|
79
79
|
orderStreamId: node.orderKey?.streamId,
|
|
80
80
|
orderStreamFrameIndex: node.orderKey?.streamFrameIndex,
|
|
81
|
+
payloadRefs: node.payloadRefs,
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
84
|
function createUserMessageRow(node) {
|
|
@@ -90,6 +91,7 @@ function createUserMessageRow(node) {
|
|
|
90
91
|
sourceNodeIds: [node.id],
|
|
91
92
|
forkEntryId: node.entryId,
|
|
92
93
|
output: text,
|
|
94
|
+
payloadRefs: node.payloadRefs,
|
|
93
95
|
};
|
|
94
96
|
}
|
|
95
97
|
function createAssistantMessageRow(node) {
|
|
@@ -101,6 +103,7 @@ function createAssistantMessageRow(node) {
|
|
|
101
103
|
sourceNodeIds: [node.id],
|
|
102
104
|
output: stringValue(node.output) || stringValue(node.summary) || "",
|
|
103
105
|
error: node.error,
|
|
106
|
+
payloadRefs: node.payloadRefs,
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
function createReasoningRow(node) {
|
|
@@ -117,6 +120,7 @@ function createReasoningRow(node) {
|
|
|
117
120
|
],
|
|
118
121
|
sourceNodeIds: [node.id],
|
|
119
122
|
markdown: text,
|
|
123
|
+
payloadRefs: node.payloadRefs,
|
|
120
124
|
};
|
|
121
125
|
}
|
|
122
126
|
function createToolRowCandidate(node, turnId) {
|
|
@@ -686,6 +690,7 @@ function detailItemsForGroup(candidates, kind) {
|
|
|
686
690
|
input: candidate.row.input,
|
|
687
691
|
output: candidate.row.output,
|
|
688
692
|
error: candidate.row.error,
|
|
693
|
+
payloadRefs: candidate.row.payloadRefs,
|
|
689
694
|
linkedPiboSessionId: candidate.row.linkedPiboSessionId,
|
|
690
695
|
previewOmission: candidate.row.previewOmission,
|
|
691
696
|
};
|
package/dist/web/http.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { gzipSync } from "node:zlib";
|
|
2
2
|
export const MAX_WEB_REQUEST_BODY_BYTES = 4 * 1024 * 1024;
|
|
3
3
|
const MIN_COMPRESS_RESPONSE_BYTES = 1024;
|
|
4
|
+
const MAX_SYNC_GZIP_RESPONSE_BYTES = 512 * 1024;
|
|
4
5
|
const INTERNAL_SOCKET_PEER_HEADER = "x-pibo-socket-peer";
|
|
5
6
|
export class PiboWebHttpError extends Error {
|
|
6
7
|
statusCode;
|
|
@@ -11,12 +12,16 @@ export class PiboWebHttpError extends Error {
|
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
export function responseJson(payload, init = {}) {
|
|
14
|
-
|
|
15
|
+
const startedAt = performance.now();
|
|
16
|
+
const body = JSON.stringify(payload);
|
|
17
|
+
const serializeMs = performance.now() - startedAt;
|
|
18
|
+
const headers = new Headers(init.headers);
|
|
19
|
+
headers.set("content-type", "application/json; charset=utf-8");
|
|
20
|
+
headers.set("x-pibo-response-bytes", String(Buffer.byteLength(body, "utf8")));
|
|
21
|
+
headers.set("server-timing", appendServerTiming(headers.get("server-timing"), `json_serialize;dur=${serializeMs.toFixed(1)}`));
|
|
22
|
+
return new Response(body, {
|
|
15
23
|
...init,
|
|
16
|
-
headers
|
|
17
|
-
"content-type": "application/json; charset=utf-8",
|
|
18
|
-
...init.headers,
|
|
19
|
-
},
|
|
24
|
+
headers,
|
|
20
25
|
});
|
|
21
26
|
}
|
|
22
27
|
export function responseHtml(html, init = {}) {
|
|
@@ -76,7 +81,7 @@ export async function sendWebResponse(response, webResponse) {
|
|
|
76
81
|
const compressEncoding = preferredResponseEncoding(response.req?.headers["accept-encoding"], webResponse);
|
|
77
82
|
if (compressEncoding && webResponse.body) {
|
|
78
83
|
const body = await readResponseBody(webResponse);
|
|
79
|
-
if (body.length >= MIN_COMPRESS_RESPONSE_BYTES) {
|
|
84
|
+
if (body.length >= MIN_COMPRESS_RESPONSE_BYTES && body.length <= MAX_SYNC_GZIP_RESPONSE_BYTES) {
|
|
80
85
|
const compressed = gzipSync(body, { level: 1 });
|
|
81
86
|
headers["content-encoding"] = compressEncoding;
|
|
82
87
|
headers["content-length"] = String(compressed.length);
|
|
@@ -85,6 +90,9 @@ export async function sendWebResponse(response, webResponse) {
|
|
|
85
90
|
response.end(compressed);
|
|
86
91
|
return;
|
|
87
92
|
}
|
|
93
|
+
if (body.length > MAX_SYNC_GZIP_RESPONSE_BYTES) {
|
|
94
|
+
headers["x-pibo-compression-skipped"] = "sync-gzip-size-limit";
|
|
95
|
+
}
|
|
88
96
|
response.writeHead(webResponse.status, headers);
|
|
89
97
|
response.end(body);
|
|
90
98
|
return;
|
|
@@ -176,3 +184,6 @@ function appendVary(existing, value) {
|
|
|
176
184
|
normalized.push(value);
|
|
177
185
|
return normalized.join(", ");
|
|
178
186
|
}
|
|
187
|
+
function appendServerTiming(existing, value) {
|
|
188
|
+
return existing ? `${existing}, ${value}` : value;
|
|
189
|
+
}
|
package/package.json
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@pasko70/pibo",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"imports": {
|
|
6
|
-
"vscode": "./src/apps/chat-vscode/extension/src/vscode-shim.js"
|
|
7
|
-
},
|
|
8
|
-
"description": "Minimal TypeScript wrapper around Pi Coding Agent.",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist",
|
|
11
|
-
"context",
|
|
12
|
-
"skills/builtin/**",
|
|
13
|
-
"docs/ops/**",
|
|
14
|
-
"README.md",
|
|
15
|
-
"src/mcp/LICENSE.mcp-cli"
|
|
16
|
-
],
|
|
17
|
-
"bin": {
|
|
18
|
-
"pibo": "dist/bin/pibo.js",
|
|
19
|
-
"rg": "dist/bin/rg.js"
|
|
20
|
-
},
|
|
21
|
-
"engines": {
|
|
22
|
-
"node": ">=24"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"dev": "tsx src/bin/pibo.ts",
|
|
26
|
-
"profile": "tsx src/bin/pibo.ts profile",
|
|
27
|
-
"tui": "tsx src/bin/pibo.ts tui",
|
|
28
|
-
"tui:routed": "tsx src/bin/pibo.ts tui:routed",
|
|
29
|
-
"tui:gateway": "tsx src/bin/pibo.ts tui gateway-producer",
|
|
30
|
-
"gateway": "tsx src/bin/pibo.ts gateway",
|
|
31
|
-
"gateway:web": "npm run web-ui:build && tsx src/bin/pibo.ts gateway:web",
|
|
32
|
-
"client": "tsx src/bin/pibo.ts client",
|
|
33
|
-
"chat-ui:build": "vite build --config src/apps/chat-ui/vite.config.ts",
|
|
34
|
-
"chat-ui:typecheck": "tsc -p src/apps/chat-ui/tsconfig.json --noEmit",
|
|
35
|
-
"context-files-ui:build": "vite build --config src/apps/context-files-ui/vite.config.ts",
|
|
36
|
-
"context-files-ui:typecheck": "tsc -p src/apps/context-files-ui/tsconfig.json --noEmit",
|
|
37
|
-
"web-ui:build": "npm run chat-ui:build && npm run context-files-ui:build",
|
|
38
|
-
"vscode:typecheck": "tsc -p src/apps/chat-vscode/extension/tsconfig.json --noEmit && tsc -p src/apps/chat-vscode/extension/webview/tsconfig.json --noEmit",
|
|
39
|
-
"vscode:webview:build": "vite build --config src/apps/chat-vscode/extension/webview/vite.config.ts",
|
|
40
|
-
"vscode:extension:build": "esbuild src/apps/chat-vscode/extension/src/extension.ts --bundle --platform=node --target=node24 --format=cjs --outfile=src/apps/chat-vscode/dist/extension/extension.cjs --external:vscode --sourcemap=inline",
|
|
41
|
-
"vscode:package": "node scripts/vscode-package.mjs",
|
|
42
|
-
"release": "node scripts/release.mjs",
|
|
43
|
-
"release:github": "node scripts/create-github-release.mjs",
|
|
44
|
-
"build": "tsc -p tsconfig.json && npm run web-ui:build && npm run vscode:webview:build && node scripts/ensure-bin-executable.mjs",
|
|
45
|
-
"start": "node dist/bin/pibo.js",
|
|
46
|
-
"test": "npm run build && node --test test/*.test.mjs test/chat-vscode/*.test.mjs",
|
|
47
|
-
"check:product-vocab": "node scripts/legacy-product-vocabulary-gate.mjs",
|
|
48
|
-
"validate:ink-web-derived": "node scripts/ink-cli-web-derived-parity-validate.mjs",
|
|
49
|
-
"compute:limited-worker-smoke": "node scripts/compute-limited-worker-smoke.mjs",
|
|
50
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && npm run chat-ui:typecheck && npm run context-files-ui:typecheck && npm run vscode:typecheck",
|
|
51
|
-
"clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"",
|
|
52
|
-
"prepack": "npm run build"
|
|
53
|
-
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"@mariozechner/pi-ai": "^0.73.1",
|
|
56
|
-
"@mariozechner/pi-coding-agent": "^0.73.1",
|
|
57
|
-
"@mdxeditor/editor": "^3.55.0",
|
|
58
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
59
|
-
"@tailwindcss/vite": "^4.2.4",
|
|
60
|
-
"@tanstack/react-query": "^5.100.7",
|
|
61
|
-
"@tanstack/react-router": "^1.168.25",
|
|
62
|
-
"@tanstack/react-start": "^1.167.50",
|
|
63
|
-
"@uiw/react-json-view": "^2.0.0-alpha.41",
|
|
64
|
-
"@vscode/ripgrep": "^1.18.0",
|
|
65
|
-
"@xyflow/react": "12.10.2",
|
|
66
|
-
"better-auth": "^1.6.9",
|
|
67
|
-
"commander": "^14.0.3",
|
|
68
|
-
"ink": "^7.0.3",
|
|
69
|
-
"lexical": "^0.35.0",
|
|
70
|
-
"lucide-react": "^0.545.0",
|
|
71
|
-
"prismjs": "^1.30.0",
|
|
72
|
-
"react": "^19.2.5",
|
|
73
|
-
"react-dom": "^19.2.5",
|
|
74
|
-
"react-markdown": "^10.1.0",
|
|
75
|
-
"react-virtuoso": "^4.18.6",
|
|
76
|
-
"remark-gfm": "^4.0.1",
|
|
77
|
-
"tailwindcss": "^4.2.4"
|
|
78
|
-
},
|
|
79
|
-
"devDependencies": {
|
|
80
|
-
"@tanstack/router-plugin": "^1.167.28",
|
|
81
|
-
"@types/node": "^25.6.0",
|
|
82
|
-
"@types/prismjs": "^1.26.6",
|
|
83
|
-
"@types/react": "^19.2.14",
|
|
84
|
-
"@types/react-dom": "^19.2.3",
|
|
85
|
-
"@vitejs/plugin-react": "^6.0.1",
|
|
86
|
-
"@vscode/vsce": "^3.6.0",
|
|
87
|
-
"esbuild": "^0.27.7",
|
|
88
|
-
"tsx": "^4.21.0",
|
|
89
|
-
"typescript": "^6.0.3",
|
|
90
|
-
"vite": "^8.0.10",
|
|
91
|
-
"vite-tsconfig-paths": "^5.1.4"
|
|
92
|
-
}
|
|
93
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@pasko70/pibo",
|
|
3
|
+
"version": "1.7.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"imports": {
|
|
6
|
+
"vscode": "./src/apps/chat-vscode/extension/src/vscode-shim.js"
|
|
7
|
+
},
|
|
8
|
+
"description": "Minimal TypeScript wrapper around Pi Coding Agent.",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"context",
|
|
12
|
+
"skills/builtin/**",
|
|
13
|
+
"docs/ops/**",
|
|
14
|
+
"README.md",
|
|
15
|
+
"src/mcp/LICENSE.mcp-cli"
|
|
16
|
+
],
|
|
17
|
+
"bin": {
|
|
18
|
+
"pibo": "dist/bin/pibo.js",
|
|
19
|
+
"rg": "dist/bin/rg.js"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=24"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "tsx src/bin/pibo.ts",
|
|
26
|
+
"profile": "tsx src/bin/pibo.ts profile",
|
|
27
|
+
"tui": "tsx src/bin/pibo.ts tui",
|
|
28
|
+
"tui:routed": "tsx src/bin/pibo.ts tui:routed",
|
|
29
|
+
"tui:gateway": "tsx src/bin/pibo.ts tui gateway-producer",
|
|
30
|
+
"gateway": "tsx src/bin/pibo.ts gateway",
|
|
31
|
+
"gateway:web": "npm run web-ui:build && tsx src/bin/pibo.ts gateway:web",
|
|
32
|
+
"client": "tsx src/bin/pibo.ts client",
|
|
33
|
+
"chat-ui:build": "vite build --config src/apps/chat-ui/vite.config.ts",
|
|
34
|
+
"chat-ui:typecheck": "tsc -p src/apps/chat-ui/tsconfig.json --noEmit",
|
|
35
|
+
"context-files-ui:build": "vite build --config src/apps/context-files-ui/vite.config.ts",
|
|
36
|
+
"context-files-ui:typecheck": "tsc -p src/apps/context-files-ui/tsconfig.json --noEmit",
|
|
37
|
+
"web-ui:build": "npm run chat-ui:build && npm run context-files-ui:build",
|
|
38
|
+
"vscode:typecheck": "tsc -p src/apps/chat-vscode/extension/tsconfig.json --noEmit && tsc -p src/apps/chat-vscode/extension/webview/tsconfig.json --noEmit",
|
|
39
|
+
"vscode:webview:build": "vite build --config src/apps/chat-vscode/extension/webview/vite.config.ts",
|
|
40
|
+
"vscode:extension:build": "esbuild src/apps/chat-vscode/extension/src/extension.ts --bundle --platform=node --target=node24 --format=cjs --outfile=src/apps/chat-vscode/dist/extension/extension.cjs --external:vscode --sourcemap=inline",
|
|
41
|
+
"vscode:package": "node scripts/vscode-package.mjs",
|
|
42
|
+
"release": "node scripts/release.mjs",
|
|
43
|
+
"release:github": "node scripts/create-github-release.mjs",
|
|
44
|
+
"build": "tsc -p tsconfig.json && npm run web-ui:build && npm run vscode:webview:build && node scripts/ensure-bin-executable.mjs",
|
|
45
|
+
"start": "node dist/bin/pibo.js",
|
|
46
|
+
"test": "npm run build && node --test test/*.test.mjs test/chat-vscode/*.test.mjs",
|
|
47
|
+
"check:product-vocab": "node scripts/legacy-product-vocabulary-gate.mjs",
|
|
48
|
+
"validate:ink-web-derived": "node scripts/ink-cli-web-derived-parity-validate.mjs",
|
|
49
|
+
"compute:limited-worker-smoke": "node scripts/compute-limited-worker-smoke.mjs",
|
|
50
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && npm run chat-ui:typecheck && npm run context-files-ui:typecheck && npm run vscode:typecheck",
|
|
51
|
+
"clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"",
|
|
52
|
+
"prepack": "npm run build"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@mariozechner/pi-ai": "^0.73.1",
|
|
56
|
+
"@mariozechner/pi-coding-agent": "^0.73.1",
|
|
57
|
+
"@mdxeditor/editor": "^3.55.0",
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
59
|
+
"@tailwindcss/vite": "^4.2.4",
|
|
60
|
+
"@tanstack/react-query": "^5.100.7",
|
|
61
|
+
"@tanstack/react-router": "^1.168.25",
|
|
62
|
+
"@tanstack/react-start": "^1.167.50",
|
|
63
|
+
"@uiw/react-json-view": "^2.0.0-alpha.41",
|
|
64
|
+
"@vscode/ripgrep": "^1.18.0",
|
|
65
|
+
"@xyflow/react": "12.10.2",
|
|
66
|
+
"better-auth": "^1.6.9",
|
|
67
|
+
"commander": "^14.0.3",
|
|
68
|
+
"ink": "^7.0.3",
|
|
69
|
+
"lexical": "^0.35.0",
|
|
70
|
+
"lucide-react": "^0.545.0",
|
|
71
|
+
"prismjs": "^1.30.0",
|
|
72
|
+
"react": "^19.2.5",
|
|
73
|
+
"react-dom": "^19.2.5",
|
|
74
|
+
"react-markdown": "^10.1.0",
|
|
75
|
+
"react-virtuoso": "^4.18.6",
|
|
76
|
+
"remark-gfm": "^4.0.1",
|
|
77
|
+
"tailwindcss": "^4.2.4"
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@tanstack/router-plugin": "^1.167.28",
|
|
81
|
+
"@types/node": "^25.6.0",
|
|
82
|
+
"@types/prismjs": "^1.26.6",
|
|
83
|
+
"@types/react": "^19.2.14",
|
|
84
|
+
"@types/react-dom": "^19.2.3",
|
|
85
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
86
|
+
"@vscode/vsce": "^3.6.0",
|
|
87
|
+
"esbuild": "^0.27.7",
|
|
88
|
+
"tsx": "^4.21.0",
|
|
89
|
+
"typescript": "^6.0.3",
|
|
90
|
+
"vite": "^8.0.10",
|
|
91
|
+
"vite-tsconfig-paths": "^5.1.4"
|
|
92
|
+
}
|
|
93
|
+
}
|