@pasko70/pibo 1.0.0 → 1.0.2
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/core/profiles.js +8 -0
- package/dist/core/runtime.js +13 -0
- package/dist/core/session-router.js +1 -0
- package/dist/plugins/builtin.js +10 -0
- package/dist/tools/desktop-env.js +9 -0
- package/dist/tools/linux-virtual-display.js +58 -0
- package/dist/tools/python-runtime.js +8 -5
- package/dist/tools/registry.js +9 -2
- package/package.json +1 -1
package/dist/core/profiles.js
CHANGED
|
@@ -3,6 +3,7 @@ export class InitialSessionContext {
|
|
|
3
3
|
profileName;
|
|
4
4
|
sessionId;
|
|
5
5
|
parentSessionId;
|
|
6
|
+
model;
|
|
6
7
|
skills;
|
|
7
8
|
tools;
|
|
8
9
|
subagents;
|
|
@@ -17,6 +18,7 @@ export class InitialSessionContext {
|
|
|
17
18
|
this.profileName = options.profileName;
|
|
18
19
|
this.sessionId = options.sessionId;
|
|
19
20
|
this.parentSessionId = options.parentSessionId;
|
|
21
|
+
this.model = options.model ? { ...options.model } : undefined;
|
|
20
22
|
this.skills = [...(options.skills ?? [])];
|
|
21
23
|
this.tools = [...(options.tools ?? [])];
|
|
22
24
|
this.subagents = [...(options.subagents ?? [])];
|
|
@@ -33,6 +35,7 @@ export class InitialSessionContextBuilder {
|
|
|
33
35
|
profileName;
|
|
34
36
|
sessionId;
|
|
35
37
|
parentSessionId;
|
|
38
|
+
model;
|
|
36
39
|
skills = [];
|
|
37
40
|
tools = [];
|
|
38
41
|
subagents = [];
|
|
@@ -54,6 +57,10 @@ export class InitialSessionContextBuilder {
|
|
|
54
57
|
this.parentSessionId = parentSessionId;
|
|
55
58
|
return this;
|
|
56
59
|
}
|
|
60
|
+
withModel(model) {
|
|
61
|
+
this.model = { ...model };
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
57
64
|
withBuiltinTools(mode) {
|
|
58
65
|
this.builtinTools = mode;
|
|
59
66
|
return this;
|
|
@@ -123,6 +130,7 @@ export class InitialSessionContextBuilder {
|
|
|
123
130
|
profileName: this.profileName,
|
|
124
131
|
sessionId: this.sessionId,
|
|
125
132
|
parentSessionId: this.parentSessionId,
|
|
133
|
+
model: this.model,
|
|
126
134
|
skills: this.skills,
|
|
127
135
|
tools: this.tools,
|
|
128
136
|
subagents: this.subagents,
|
package/dist/core/runtime.js
CHANGED
|
@@ -201,6 +201,7 @@ export async function createPiboRuntime(options = {}) {
|
|
|
201
201
|
services,
|
|
202
202
|
sessionManager: runtimeSessionManager,
|
|
203
203
|
sessionStartEvent,
|
|
204
|
+
model: resolveProfileModel(profile, services),
|
|
204
205
|
thinkingLevel: options.thinkingLevel,
|
|
205
206
|
customTools,
|
|
206
207
|
noTools: profile.builtinTools === "disabled" ? "builtin" : undefined,
|
|
@@ -228,6 +229,18 @@ export async function createPiboRuntime(options = {}) {
|
|
|
228
229
|
sessionManager,
|
|
229
230
|
});
|
|
230
231
|
}
|
|
232
|
+
function resolveProfileModel(profile, services) {
|
|
233
|
+
if (!profile.model)
|
|
234
|
+
return undefined;
|
|
235
|
+
const model = services.modelRegistry.find(profile.model.provider, profile.model.id);
|
|
236
|
+
if (!model) {
|
|
237
|
+
throw new Error(`Profile "${profile.profileName}" requests unknown model ${profile.model.provider}/${profile.model.id}.`);
|
|
238
|
+
}
|
|
239
|
+
if (!services.modelRegistry.hasConfiguredAuth(model)) {
|
|
240
|
+
throw new Error(`Profile "${profile.profileName}" requires configured auth for ${profile.model.provider}/${profile.model.id}.`);
|
|
241
|
+
}
|
|
242
|
+
return model;
|
|
243
|
+
}
|
|
231
244
|
export async function inspectPiboProfile(options = {}) {
|
|
232
245
|
const cwd = options.cwd ?? process.cwd();
|
|
233
246
|
const profile = options.profile ?? createDefaultPiboProfile();
|
|
@@ -14,6 +14,7 @@ function profileForSession(baseProfile, piSessionId, parentPiSessionId) {
|
|
|
14
14
|
profileName: baseProfile.profileName,
|
|
15
15
|
sessionId: piSessionId,
|
|
16
16
|
parentSessionId: parentPiSessionId,
|
|
17
|
+
model: baseProfile.model,
|
|
17
18
|
skills: baseProfile.skills,
|
|
18
19
|
tools: baseProfile.tools,
|
|
19
20
|
subagents: baseProfile.subagents,
|
package/dist/plugins/builtin.js
CHANGED
|
@@ -98,6 +98,16 @@ export const piboCorePlugin = definePiboPlugin({
|
|
|
98
98
|
.createSession();
|
|
99
99
|
},
|
|
100
100
|
});
|
|
101
|
+
api.registerProfile({
|
|
102
|
+
name: "pibo-kimi-coding",
|
|
103
|
+
aliases: ["kimi", "kimi-coding"],
|
|
104
|
+
description: "Pibo profile pinned to Kimi For Coding. Requires KIMI_API_KEY or configured kimi-coding auth.",
|
|
105
|
+
create(context) {
|
|
106
|
+
return createBaseProfileBuilder("pibo-kimi-coding", context)
|
|
107
|
+
.withModel({ provider: "kimi-coding", id: "kimi-for-coding" })
|
|
108
|
+
.createSession();
|
|
109
|
+
},
|
|
110
|
+
});
|
|
101
111
|
api.registerGatewayAction({
|
|
102
112
|
name: "status",
|
|
103
113
|
description: "Return current session status.",
|
|
@@ -88,3 +88,12 @@ export function printDesktopEnvStatus(indent = ' ') {
|
|
|
88
88
|
console.log(`${indent}desktop: not detected`);
|
|
89
89
|
console.log(`${indent}warning: headed browser mode is unavailable; use headless mode or start a desktop display first.`);
|
|
90
90
|
}
|
|
91
|
+
export function printLinuxVirtualDisplayHint(indent = ' ') {
|
|
92
|
+
if (process.platform !== 'linux')
|
|
93
|
+
return;
|
|
94
|
+
console.log(`${indent}linux headed browser hint:`);
|
|
95
|
+
console.log(`${indent} Install a virtual X display if this host has no desktop session.`);
|
|
96
|
+
console.log(`${indent} Ubuntu/Debian: sudo apt update && sudo apt install -y xvfb xauth x11-xserver-utils`);
|
|
97
|
+
console.log(`${indent} Start one display: Xvfb :0 -screen 0 1920x1080x24 -ac -nolisten tcp`);
|
|
98
|
+
console.log(`${indent} Then export DISPLAY=:0 before running browser-use.`);
|
|
99
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { writeFile } from 'node:fs/promises';
|
|
3
|
+
import { detectDesktopEnv, hasDesktopDisplay, printLinuxVirtualDisplayHint } from './desktop-env.js';
|
|
4
|
+
export const PIBO_XVFB_SERVICE_NAME = 'pibo-xvfb.service';
|
|
5
|
+
export const PIBO_XVFB_SERVICE_PATH = `/etc/systemd/system/${PIBO_XVFB_SERVICE_NAME}`;
|
|
6
|
+
export function createPiboXvfbServiceUnit() {
|
|
7
|
+
return [
|
|
8
|
+
'[Unit]',
|
|
9
|
+
'Description=Virtual X display for Pibo browser automation',
|
|
10
|
+
'After=network.target',
|
|
11
|
+
'',
|
|
12
|
+
'[Service]',
|
|
13
|
+
'Type=simple',
|
|
14
|
+
'ExecStart=/usr/bin/Xvfb :0 -screen 0 1920x1080x24 -ac -nolisten tcp',
|
|
15
|
+
'Restart=always',
|
|
16
|
+
'RestartSec=2',
|
|
17
|
+
'',
|
|
18
|
+
'[Install]',
|
|
19
|
+
'WantedBy=multi-user.target',
|
|
20
|
+
'',
|
|
21
|
+
].join('\n');
|
|
22
|
+
}
|
|
23
|
+
function isRootUser() {
|
|
24
|
+
return typeof process.getuid === 'function' && process.getuid() === 0;
|
|
25
|
+
}
|
|
26
|
+
async function waitForDisplaySocket(timeoutMs = 5000) {
|
|
27
|
+
const deadline = Date.now() + timeoutMs;
|
|
28
|
+
while (Date.now() < deadline) {
|
|
29
|
+
if (existsSync('/tmp/.X11-unix/X0'))
|
|
30
|
+
return true;
|
|
31
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
32
|
+
}
|
|
33
|
+
return existsSync('/tmp/.X11-unix/X0');
|
|
34
|
+
}
|
|
35
|
+
export async function ensureLinuxVirtualDisplay(options) {
|
|
36
|
+
if (process.platform !== 'linux')
|
|
37
|
+
return false;
|
|
38
|
+
if (hasDesktopDisplay(detectDesktopEnv()))
|
|
39
|
+
return false;
|
|
40
|
+
if (!isRootUser()) {
|
|
41
|
+
console.log('No desktop display detected and automatic virtual display setup requires root.');
|
|
42
|
+
printLinuxVirtualDisplayHint(' ');
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
console.log('No desktop display detected. Provisioning virtual X display for browser-use.');
|
|
46
|
+
await options.runInherited('apt-get', ['update']);
|
|
47
|
+
await options.runInherited('apt-get', ['install', '-y', 'xvfb', 'xauth', 'x11-xserver-utils']);
|
|
48
|
+
await writeFile(PIBO_XVFB_SERVICE_PATH, createPiboXvfbServiceUnit(), 'utf8');
|
|
49
|
+
await options.runInherited('systemctl', ['daemon-reload']);
|
|
50
|
+
await options.runInherited('systemctl', ['enable', '--now', PIBO_XVFB_SERVICE_NAME]);
|
|
51
|
+
process.env.DISPLAY = ':0';
|
|
52
|
+
const ready = await waitForDisplaySocket();
|
|
53
|
+
if (!ready) {
|
|
54
|
+
throw new Error('Virtual X display service was installed but DISPLAY :0 did not become ready.');
|
|
55
|
+
}
|
|
56
|
+
console.log('Virtual X display ready on DISPLAY=:0');
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
@@ -4,7 +4,7 @@ import { mkdir, rm } from 'node:fs/promises';
|
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { ErrorCode, formatCliError } from '../cli-errors.js';
|
|
7
|
-
import { getDesktopProcessEnv, printDesktopEnvStatus } from './desktop-env.js';
|
|
7
|
+
import { detectDesktopEnv, getDesktopProcessEnv, hasDesktopDisplay, printDesktopEnvStatus, printLinuxVirtualDisplayHint, } from './desktop-env.js';
|
|
8
8
|
function getPiboHome() {
|
|
9
9
|
return process.env.PIBO_HOME || join(homedir(), '.pibo');
|
|
10
10
|
}
|
|
@@ -49,7 +49,7 @@ function runBuffered(command, args, env = process.env) {
|
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
-
function
|
|
52
|
+
export function runInheritedCommand(command, args, env = process.env) {
|
|
53
53
|
return new Promise((resolve, reject) => {
|
|
54
54
|
console.log(`Running: ${command} ${args.join(' ')}`);
|
|
55
55
|
const child = spawn(command, args, {
|
|
@@ -94,6 +94,9 @@ export async function printToolPythonRuntimeDoctor(name, spec) {
|
|
|
94
94
|
console.log(` venv: ${existsSync(paths.venvDir) ? 'present' : 'missing'}`);
|
|
95
95
|
console.log(` executable: ${existsSync(paths.executablePath) ? paths.executablePath : 'missing'}`);
|
|
96
96
|
printDesktopEnvStatus(' ');
|
|
97
|
+
if (name === 'browser-use' && process.platform === 'linux' && !hasDesktopDisplay(detectDesktopEnv())) {
|
|
98
|
+
printLinuxVirtualDisplayHint(' ');
|
|
99
|
+
}
|
|
97
100
|
if (existsSync(paths.executablePath)) {
|
|
98
101
|
const doctor = await runBuffered(paths.executablePath, ['doctor'], getToolPythonRuntimeEnv(paths, spec));
|
|
99
102
|
console.log(` tool doctor: ${doctor.ok ? 'ok' : 'failed'}`);
|
|
@@ -133,9 +136,9 @@ export async function installToolPythonRuntime(name, spec) {
|
|
|
133
136
|
await mkdir(paths.rootDir, { recursive: true });
|
|
134
137
|
await mkdir(paths.homeDir, { recursive: true });
|
|
135
138
|
if (!existsSync(paths.venvDir)) {
|
|
136
|
-
await
|
|
139
|
+
await runInheritedCommand('uv', ['venv', paths.venvDir, '--python', spec.pythonVersion]);
|
|
137
140
|
}
|
|
138
|
-
await
|
|
141
|
+
await runInheritedCommand('uv', [
|
|
139
142
|
'pip',
|
|
140
143
|
'install',
|
|
141
144
|
'--python',
|
|
@@ -143,7 +146,7 @@ export async function installToolPythonRuntime(name, spec) {
|
|
|
143
146
|
spec.packageName,
|
|
144
147
|
]);
|
|
145
148
|
if (spec.postInstallArgs?.length) {
|
|
146
|
-
await
|
|
149
|
+
await runInheritedCommand(paths.executablePath, spec.postInstallArgs, getToolPythonRuntimeEnv(paths, spec));
|
|
147
150
|
}
|
|
148
151
|
return paths;
|
|
149
152
|
}
|
package/dist/tools/registry.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { printDesktopEnvStatus } from './desktop-env.js';
|
|
2
|
+
import { detectDesktopEnv, hasDesktopDisplay, printDesktopEnvStatus, printLinuxVirtualDisplayHint } from './desktop-env.js';
|
|
3
3
|
import { BROWSER_USE_GUIDE, REMOTE_BROWSER_GUIDE } from './guides.js';
|
|
4
|
-
import {
|
|
4
|
+
import { ensureLinuxVirtualDisplay } from './linux-virtual-display.js';
|
|
5
|
+
import { getToolPythonRuntimePaths, installToolPythonRuntime, runInheritedCommand, printToolPythonRuntimeDoctor, removeToolPythonRuntime, } from './python-runtime.js';
|
|
5
6
|
const MAX_AGENT_CONTEXT_SNIPPET_LENGTH = 480;
|
|
6
7
|
const INSTALLED_TOOLS_CONTEXT_PATH = '.pibo/context/installed-pibo-tools.md';
|
|
7
8
|
const REGISTRY = [
|
|
@@ -90,6 +91,9 @@ export function getInstalledCliToolContextFile() {
|
|
|
90
91
|
}
|
|
91
92
|
export async function installCliTool(entry, runSetup) {
|
|
92
93
|
if (runSetup) {
|
|
94
|
+
if (entry.name === 'browser-use') {
|
|
95
|
+
await ensureLinuxVirtualDisplay({ runInherited: runInheritedCommand });
|
|
96
|
+
}
|
|
93
97
|
await installToolPythonRuntime(entry.name, entry.runtime);
|
|
94
98
|
}
|
|
95
99
|
const status = getCliToolStatus(entry);
|
|
@@ -97,6 +101,9 @@ export async function installCliTool(entry, runSetup) {
|
|
|
97
101
|
console.log(` executable: ${status.executablePath}`);
|
|
98
102
|
console.log(` home: ${status.homeDir}`);
|
|
99
103
|
printDesktopEnvStatus(' ');
|
|
104
|
+
if (entry.name === 'browser-use' && process.platform === 'linux' && !hasDesktopDisplay(detectDesktopEnv())) {
|
|
105
|
+
printLinuxVirtualDisplayHint(' ');
|
|
106
|
+
}
|
|
100
107
|
console.log(` env: pibo tools env ${entry.name}`);
|
|
101
108
|
}
|
|
102
109
|
export async function removeCliTool(entry) {
|