pi-web 0.14.2 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,16 +19,9 @@ For remote access, use the **recommended** Tailscale HTTPS setup below.
19
19
  ```
20
20
  --port <number> Port to listen on (default: 8192)
21
21
  --host <string> Host to bind to (default: 127.0.0.1)
22
- --agent <pi|omp> Agent backend profile (default: pi)
23
22
  --help Show help
24
23
  ```
25
24
 
26
- To run against Oh My Pi, start with:
27
-
28
- ```bash
29
- npx -y pi-web@latest --agent omp
30
- ```
31
-
32
25
  ## Recommended: secure access with Tailscale (HTTPS, no app password)
33
26
 
34
27
  `pi-web` does not include built-in authentication. **Recommended setup:** keep it bound to `127.0.0.1` (IPv4 loopback) and expose it only through your private Tailnet.
@@ -93,8 +86,7 @@ Notes:
93
86
  git clone https://github.com/ravshansbox/pi-web
94
87
  cd pi-web
95
88
  npm install
96
- npm run dev:pi # Pi backend
97
- npm run dev:omp # Oh My Pi backend
89
+ npm run dev
98
90
  ```
99
91
 
100
92
  Requires Node.js 22+.
@@ -7,7 +7,7 @@ import { homedir } from 'node:os';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  import { WebSocketServer, WebSocket } from 'ws';
9
9
  import { RpcSession } from './rpc.js';
10
- import { listSessions, readSessionMessages, getSessionFilePath, } from './sessions.js';
10
+ import { listSessions, readSessionMessages, getSessionFilePath } from './sessions.js';
11
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
12
12
  if (process.argv.includes('--help') || process.argv.includes('-h')) {
13
13
  console.log(`
@@ -18,7 +18,6 @@ Usage: pi-web [options]
18
18
  Options:
19
19
  --port <number> Port to listen on (default: 8192)
20
20
  --host <string> Host to bind to (default: 127.0.0.1)
21
- --agent <pi|omp> Agent backend profile (default: pi)
22
21
  -h, --help Show this help message
23
22
  `.trim());
24
23
  process.exit(0);
@@ -33,22 +32,9 @@ function getArg(name) {
33
32
  return process.argv[idx + 1];
34
33
  return undefined;
35
34
  }
36
- function parseAgent(value) {
37
- const agent = (value || 'pi').toLowerCase();
38
- if (agent === 'pi' || agent === 'omp')
39
- return agent;
40
- console.error(`invalid --agent value "${value}". expected "pi" or "omp"`);
41
- process.exit(1);
42
- }
43
- function getAgentCommand(agent) {
44
- return agent === 'omp'
45
- ? { command: 'npx', args: ['-y', '@earendil-works/pi-coding-agent@latest'] }
46
- : { command: 'npx', args: ['-y', '@earendil-works/pi-coding-agent@latest'] };
47
- }
48
- const AGENT = parseAgent(getArg('agent'));
35
+ const AGENT_CMD = { command: 'npx', args: ['-y', '@earendil-works/pi-coding-agent@latest'] };
49
36
  const PORT = parseInt(getArg('port') || '8192', 10);
50
37
  const HOST = getArg('host') || '127.0.0.1';
51
- const AGENT_CMD = getAgentCommand(AGENT);
52
38
  const IDLE_SESSION_TTL_MS = 60_000;
53
39
  const isWatchMode = process.argv.includes('--watch') ||
54
40
  process.execArgv.some((arg) => arg === '--watch' || arg.startsWith('--watch-'));
@@ -59,7 +45,7 @@ const distDir = distDirCandidates.find((candidate) => existsSync(join(candidate,
59
45
  const htmlPath = join(distDir, 'index.html');
60
46
  const htmlCache = isDev || !existsSync(htmlPath) ? null : readFileSync(htmlPath, 'utf-8');
61
47
  const HOME_DIR = resolve(homedir() || '/');
62
- const SESSION_ROOT = resolve(join(HOME_DIR, AGENT === 'omp' ? '.omp' : '.pi', 'agent', 'sessions'));
48
+ const SESSION_ROOT = resolve(join(HOME_DIR, '.pi', 'agent', 'sessions'));
63
49
  function isWithinRoot(path, root) {
64
50
  const rel = relative(root, path);
65
51
  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
@@ -116,7 +102,7 @@ function isValidSessionFilename(filename) {
116
102
  function resolveSessionPath(cwd, filename) {
117
103
  if (!isValidSessionFilename(filename))
118
104
  return null;
119
- const resolved = resolve(getSessionFilePath(cwd, filename, AGENT));
105
+ const resolved = resolve(getSessionFilePath(cwd, filename));
120
106
  return isWithinRoot(resolved, SESSION_ROOT) ? resolved : null;
121
107
  }
122
108
  const server = createServer((req, res) => {
@@ -133,7 +119,7 @@ const server = createServer((req, res) => {
133
119
  if (req.url?.startsWith('/api/sessions')) {
134
120
  const url = new URL(req.url, `http://${req.headers.host}`);
135
121
  const cwd = url.searchParams.get('cwd') || undefined;
136
- listSessions({ cwd, limit: 50, agent: AGENT })
122
+ listSessions({ cwd, limit: 50 })
137
123
  .then((data) => {
138
124
  const sessionsWithRuntime = data.map((session) => ({
139
125
  ...session,
@@ -369,7 +355,7 @@ function updateSessionModelCapability(managed, event) {
369
355
  }
370
356
  }
371
357
  function createManagedSession(cwd, sessionFile, initialKey) {
372
- const sessionPath = sessionFile ? getSessionFilePath(cwd, sessionFile, AGENT) : undefined;
358
+ const sessionPath = sessionFile ? getSessionFilePath(cwd, sessionFile) : undefined;
373
359
  let managed = null;
374
360
  const rpc = new RpcSession({
375
361
  piCmd: AGENT_CMD,
@@ -4,34 +4,25 @@ import { homedir } from 'node:os';
4
4
  import { createReadStream } from 'node:fs';
5
5
  import { createInterface } from 'node:readline';
6
6
  const HOME_DIR = resolve(homedir());
7
- function getSessionDir(agent) {
8
- const configDir = agent === 'omp' ? '.omp' : '.pi';
9
- return join(HOME_DIR, configDir, 'agent', 'sessions');
7
+ function getSessionDir() {
8
+ return join(HOME_DIR, '.pi', 'agent', 'sessions');
10
9
  }
11
- function cwdToSessionDir(cwd, agent) {
10
+ function cwdToSessionDir(cwd) {
12
11
  const normalisedCwd = resolve(cwd);
13
- if (agent === 'omp') {
14
- if (normalisedCwd === HOME_DIR ||
15
- normalisedCwd.startsWith(`${HOME_DIR}/`) ||
16
- normalisedCwd.startsWith(`${HOME_DIR}\\`)) {
17
- const relative = normalisedCwd.slice(HOME_DIR.length).replace(/^[/\\]/, '');
18
- return `-${relative.replace(/[/\\:]/g, '-')}`;
19
- }
20
- }
21
12
  const encoded = normalisedCwd.replace(/^[/\\]/, '').replace(/[/\\:]/g, '-');
22
13
  return `--${encoded}--`;
23
14
  }
24
- export function getSessionFilePath(cwd, filename, agent = 'pi') {
25
- return join(getSessionDir(agent), cwdToSessionDir(cwd, agent), filename);
15
+ export function getSessionFilePath(cwd, filename) {
16
+ return join(getSessionDir(), cwdToSessionDir(cwd), filename);
26
17
  }
27
18
  export async function listSessions(opts) {
28
- const { cwd, limit = 30, agent = 'pi' } = opts;
19
+ const { cwd, limit = 30 } = opts;
29
20
  const results = [];
30
- const sessionDir = getSessionDir(agent);
21
+ const sessionDir = getSessionDir();
31
22
  try {
32
23
  const cwdDirs = await readdir(sessionDir, { withFileTypes: true });
33
24
  const targetDirs = cwd
34
- ? cwdDirs.filter((d) => d.isDirectory() && d.name === cwdToSessionDir(cwd, agent))
25
+ ? cwdDirs.filter((d) => d.isDirectory() && d.name === cwdToSessionDir(cwd))
35
26
  : cwdDirs.filter((d) => d.isDirectory());
36
27
  for (const dir of targetDirs) {
37
28
  const dirPath = join(sessionDir, dir.name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web",
3
- "version": "0.14.2",
3
+ "version": "0.14.3",
4
4
  "type": "module",
5
5
  "description": "Web UI for the pi coding agent",
6
6
  "repository": {
@@ -24,9 +24,7 @@
24
24
  "LICENSE"
25
25
  ],
26
26
  "scripts": {
27
- "dev": "npm run dev:pi",
28
- "dev:pi": "concurrently \"vite build --watch\" \"tsc -w -p tsconfig.server.json\" \"node --watch build/server/server.js --agent pi\"",
29
- "dev:omp": "concurrently \"vite build --watch\" \"tsc -w -p tsconfig.server.json\" \"node --watch build/server/server.js --agent omp\"",
27
+ "dev": "concurrently \"vite build --watch\" \"tsc -w -p tsconfig.server.json\" \"node --watch build/server/server.js\"",
30
28
  "build": "vite build && tsc -p tsconfig.server.json",
31
29
  "build:bin": "node scripts/generate-bin.mjs",
32
30
  "test:smoke": "node scripts/smoke-checks.mjs",