pi-web-ui 0.63.4 → 0.64.0
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/LICENSE +21 -21
- package/README.md +504 -504
- package/README.zh-CN.md +427 -427
- package/bin/pi-web-ui.mjs +1809 -1809
- package/deploy/com.xingshuyin.pi-web-ui.plist +48 -48
- package/deploy/nginx-subpath.conf +88 -88
- package/deploy/pi-web-ui-task.xml +54 -54
- package/deploy/pi-web-ui.service +31 -31
- package/dist/server/agent-service.js +18 -10
- package/dist/server/attachments.js +3 -3
- package/dist/server/dsh/dsh-agent-service.js +3 -0
- package/dist/server/dsh/runtime/cordis.yml +1 -1
- package/dist/server/dsh/runtime/goal-rpc.mjs +645 -645
- package/dist/server/dsh/runtime/launcher.mjs +164 -164
- package/dist/server/dsh/runtime/override.patch.yml +71 -71
- package/dist/server/dsh/runtime/runtime-root.mjs +86 -86
- package/dist/server/files-service.js +42 -0
- package/dist/server/index.js +3 -0
- package/dist/server/marker-service.js +2 -1
- package/dist/server/markers/builtins/rename.js +1 -3
- package/dist/server/markers/builtins/services.js +6 -2
- package/dist/server/markers/builtins/todo.js +8 -4
- package/dist/server/settings-service.js +5 -1
- package/dist/server/terminals.js +4 -4
- package/dist/server/vision-bridge.js +9 -9
- package/extensions/webui.ts +190 -190
- package/package.json +1 -1
- package/themes/cyberpunk.css +81 -81
- package/themes/dazzle.css +81 -81
- package/themes/md-preview.css +98 -98
- package/themes/white.css +160 -160
- package/web/dist/assets/{TerminalPanel-BFrV6B8W.js → TerminalPanel-DNkAT34Z.js} +1 -1
- package/web/dist/assets/index-CMgDryBL.css +10 -0
- package/web/dist/assets/index-_1vyEugI.js +326 -0
- package/web/dist/favicon.svg +8 -8
- package/web/dist/index.html +21 -21
- package/web/dist/manifest.webmanifest +50 -50
- package/web/dist/sw.js +126 -126
- package/web/public/favicon.svg +8 -8
- package/web/public/manifest.webmanifest +50 -50
- package/web/public/sw.js +126 -126
- package/web/dist/assets/index-BFoSybNe.js +0 -324
- package/web/dist/assets/index-D9G_7fPE.css +0 -10
package/web/dist/favicon.svg
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
-
<!-- pi symbol favicon: violet rounded square + white π (drawn as paths,
|
|
3
|
-
no font dependency) -->
|
|
4
|
-
<rect width="64" height="64" rx="14" fill="#8b5cf6"/>
|
|
5
|
-
<rect x="14" y="17" width="36" height="6.5" rx="3.25" fill="#ffffff"/>
|
|
6
|
-
<rect x="17.5" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
7
|
-
<rect x="40" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
8
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<!-- pi symbol favicon: violet rounded square + white π (drawn as paths,
|
|
3
|
+
no font dependency) -->
|
|
4
|
+
<rect width="64" height="64" rx="14" fill="#8b5cf6"/>
|
|
5
|
+
<rect x="14" y="17" width="36" height="6.5" rx="3.25" fill="#ffffff"/>
|
|
6
|
+
<rect x="17.5" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
7
|
+
<rect x="40" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
8
|
+
</svg>
|
package/web/dist/index.html
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<meta name="color-scheme" content="dark" />
|
|
7
|
-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
8
|
-
<!-- PWA manifest: relative so nginx sub-path deployments (/pi/) resolve correctly -->
|
|
9
|
-
<link rel="manifest" href="./manifest.webmanifest" />
|
|
10
|
-
<meta name="theme-color" content="#0f172a" />
|
|
11
|
-
<link rel="apple-touch-icon" href="./icons/icon-192.png" />
|
|
12
|
-
<meta name="mobile-web-app-capable" content="yes" />
|
|
13
|
-
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
14
|
-
<title>pi-web-ui — pi 编码智能体</title>
|
|
15
|
-
<script type="module" crossorigin src="/assets/index-
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="color-scheme" content="dark" />
|
|
7
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
8
|
+
<!-- PWA manifest: relative so nginx sub-path deployments (/pi/) resolve correctly -->
|
|
9
|
+
<link rel="manifest" href="./manifest.webmanifest" />
|
|
10
|
+
<meta name="theme-color" content="#0f172a" />
|
|
11
|
+
<link rel="apple-touch-icon" href="./icons/icon-192.png" />
|
|
12
|
+
<meta name="mobile-web-app-capable" content="yes" />
|
|
13
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
14
|
+
<title>pi-web-ui — pi 编码智能体</title>
|
|
15
|
+
<script type="module" crossorigin src="/assets/index-_1vyEugI.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/assets/markdown-DRBrS2Nf.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/react-C9ovnpIm.js">
|
|
18
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
19
|
-
</head>
|
|
20
|
-
<body>
|
|
21
|
-
<div id="root"></div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
|
18
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CMgDryBL.css">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div id="root"></div>
|
|
22
|
+
</body>
|
|
23
|
+
</html>
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-web-ui — pi coding agent",
|
|
3
|
-
"short_name": "pi-web-ui",
|
|
4
|
-
"description": "The polished browser cockpit for the pi coding agent. Stream conversations, inspect tool calls, manage files and run your workspace.",
|
|
5
|
-
"start_url": "./",
|
|
6
|
-
"scope": "./",
|
|
7
|
-
"display": "standalone",
|
|
8
|
-
"orientation": "any",
|
|
9
|
-
"background_color": "#0f172a",
|
|
10
|
-
"theme_color": "#0f172a",
|
|
11
|
-
"categories": ["developer tools", "productivity"],
|
|
12
|
-
"icons": [
|
|
13
|
-
{
|
|
14
|
-
"src": "./icons/icon-192.png",
|
|
15
|
-
"sizes": "192x192",
|
|
16
|
-
"type": "image/png",
|
|
17
|
-
"purpose": "any"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"src": "./icons/icon-512.png",
|
|
21
|
-
"sizes": "512x512",
|
|
22
|
-
"type": "image/png",
|
|
23
|
-
"purpose": "any"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"src": "./icons/icon-1024.png",
|
|
27
|
-
"sizes": "1024x1024",
|
|
28
|
-
"type": "image/png",
|
|
29
|
-
"purpose": "any"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"src": "./icons/maskable-192.png",
|
|
33
|
-
"sizes": "192x192",
|
|
34
|
-
"type": "image/png",
|
|
35
|
-
"purpose": "maskable"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"src": "./icons/maskable-512.png",
|
|
39
|
-
"sizes": "512x512",
|
|
40
|
-
"type": "image/png",
|
|
41
|
-
"purpose": "maskable"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"src": "./icons/maskable-1024.png",
|
|
45
|
-
"sizes": "1024x1024",
|
|
46
|
-
"type": "image/png",
|
|
47
|
-
"purpose": "maskable"
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-web-ui — pi coding agent",
|
|
3
|
+
"short_name": "pi-web-ui",
|
|
4
|
+
"description": "The polished browser cockpit for the pi coding agent. Stream conversations, inspect tool calls, manage files and run your workspace.",
|
|
5
|
+
"start_url": "./",
|
|
6
|
+
"scope": "./",
|
|
7
|
+
"display": "standalone",
|
|
8
|
+
"orientation": "any",
|
|
9
|
+
"background_color": "#0f172a",
|
|
10
|
+
"theme_color": "#0f172a",
|
|
11
|
+
"categories": ["developer tools", "productivity"],
|
|
12
|
+
"icons": [
|
|
13
|
+
{
|
|
14
|
+
"src": "./icons/icon-192.png",
|
|
15
|
+
"sizes": "192x192",
|
|
16
|
+
"type": "image/png",
|
|
17
|
+
"purpose": "any"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"src": "./icons/icon-512.png",
|
|
21
|
+
"sizes": "512x512",
|
|
22
|
+
"type": "image/png",
|
|
23
|
+
"purpose": "any"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"src": "./icons/icon-1024.png",
|
|
27
|
+
"sizes": "1024x1024",
|
|
28
|
+
"type": "image/png",
|
|
29
|
+
"purpose": "any"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"src": "./icons/maskable-192.png",
|
|
33
|
+
"sizes": "192x192",
|
|
34
|
+
"type": "image/png",
|
|
35
|
+
"purpose": "maskable"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"src": "./icons/maskable-512.png",
|
|
39
|
+
"sizes": "512x512",
|
|
40
|
+
"type": "image/png",
|
|
41
|
+
"purpose": "maskable"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"src": "./icons/maskable-1024.png",
|
|
45
|
+
"sizes": "1024x1024",
|
|
46
|
+
"type": "image/png",
|
|
47
|
+
"purpose": "maskable"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
package/web/dist/sw.js
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pi-web-ui — Progressive Web App service worker.
|
|
3
|
-
*
|
|
4
|
-
* Strategy overview
|
|
5
|
-
* -----------------
|
|
6
|
-
* pi-web-ui is a WebSocket-first app that needs a live backend, so we do NOT
|
|
7
|
-
* try to make it fully offline. Instead the SW focuses on what makes it a
|
|
8
|
-
* reliable *installable* PWA on mobile/desktop:
|
|
9
|
-
*
|
|
10
|
-
* - network-first for navigation requests (falls back to the cached app
|
|
11
|
-
* shell when the network flaps), and
|
|
12
|
-
* - cache-first for hashed static assets, which Vite fingerprints so a cache
|
|
13
|
-
* hit is always the right version until a new deploy publishes new hashes.
|
|
14
|
-
*
|
|
15
|
-
* Real-time / dynamic / credential-bearing routes (/ws, /api, /themes,
|
|
16
|
-
* /plugins) are always fetched from the network and never cached, so we never
|
|
17
|
-
* risk serving stale theme/plugin code or caching anything sensitive.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
const STATIC_CACHE = "pi-web-ui-static-v1";
|
|
21
|
-
const SHELL_CACHE = "pi-web-ui-shell-v1";
|
|
22
|
-
|
|
23
|
-
// App root within this origin — "/" for root deployments, "/pi/" behind an
|
|
24
|
-
// nginx sub-path reverse proxy. All path checks below are relative to it, so
|
|
25
|
-
// the worker behaves identically under either deployment layout.
|
|
26
|
-
const SCOPE = new URL("./", self.registration.scope).pathname;
|
|
27
|
-
|
|
28
|
-
/** Map a request pathname to an app-relative path ("/pi/ws" → "/ws"), or null
|
|
29
|
-
* when the request lies outside the registration scope (shouldn't happen). */
|
|
30
|
-
function appPath(pathname) {
|
|
31
|
-
if (SCOPE === "/") return pathname;
|
|
32
|
-
if (pathname.startsWith(SCOPE)) return "/" + pathname.slice(SCOPE.length);
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
self.addEventListener("install", (event) => {
|
|
37
|
-
// Take control as soon as this version activates so the current page is
|
|
38
|
-
// served by the new worker without requiring a second reload.
|
|
39
|
-
self.skipWaiting();
|
|
40
|
-
event.waitUntil(caches.open(SHELL_CACHE));
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
self.addEventListener("activate", (event) => {
|
|
44
|
-
event.waitUntil(
|
|
45
|
-
caches
|
|
46
|
-
.keys()
|
|
47
|
-
.then((keys) =>
|
|
48
|
-
Promise.all(keys.filter((k) => k !== STATIC_CACHE && k !== SHELL_CACHE).map((k) => caches.delete(k))),
|
|
49
|
-
)
|
|
50
|
-
// Apply to already-open pages immediately.
|
|
51
|
-
.then(() => self.clients.claim()),
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// Only cache simple, safe GET requests. Everything else goes straight through.
|
|
56
|
-
function isCachable(request) {
|
|
57
|
-
const method = request.method;
|
|
58
|
-
if (method !== "GET") return false;
|
|
59
|
-
|
|
60
|
-
const url = new URL(request.url);
|
|
61
|
-
if (url.origin !== self.location.origin) return false;
|
|
62
|
-
|
|
63
|
-
// Never cache real-time, dynamic or credential/data endpoints.
|
|
64
|
-
const path = appPath(url.pathname);
|
|
65
|
-
if (
|
|
66
|
-
path === null ||
|
|
67
|
-
path.startsWith("/ws") ||
|
|
68
|
-
path.startsWith("/api") ||
|
|
69
|
-
path.startsWith("/themes") ||
|
|
70
|
-
path.startsWith("/plugins")
|
|
71
|
-
) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
self.addEventListener("fetch", (event) => {
|
|
78
|
-
const { request } = event;
|
|
79
|
-
if (!isCachable(request)) {
|
|
80
|
-
// Let the browser/backend handle WebSockets, API calls and cross-origin
|
|
81
|
-
// requests normally.
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const requestUrl = new URL(request.url);
|
|
86
|
-
|
|
87
|
-
// Navigation → app shell. Network-first with cached fallback: users get the
|
|
88
|
-
// latest build when online but can still reopen the app while flaky.
|
|
89
|
-
if (request.mode === "navigate") {
|
|
90
|
-
event.respondWith(
|
|
91
|
-
fetch(request)
|
|
92
|
-
.then((response) => {
|
|
93
|
-
const copy = response.clone();
|
|
94
|
-
caches.open(SHELL_CACHE).then((cache) => cache.put(request, copy));
|
|
95
|
-
return response;
|
|
96
|
-
})
|
|
97
|
-
.catch(() => caches.match(request).then((cached) => cached || caches.match(SCOPE) || Response.error())),
|
|
98
|
-
);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Static assets (hashed by Vite) → cache-first.
|
|
103
|
-
const path = appPath(requestUrl.pathname);
|
|
104
|
-
const isStatic =
|
|
105
|
-
path !== null &&
|
|
106
|
-
(path.startsWith("/assets/") ||
|
|
107
|
-
path.startsWith("/icons/") ||
|
|
108
|
-
path === "/favicon.svg" ||
|
|
109
|
-
path === "/icon.ico" ||
|
|
110
|
-
path === "/manifest.webmanifest");
|
|
111
|
-
|
|
112
|
-
if (isStatic) {
|
|
113
|
-
event.respondWith(
|
|
114
|
-
caches.match(request).then((cached) => {
|
|
115
|
-
if (cached) return cached;
|
|
116
|
-
return fetch(request).then((response) => {
|
|
117
|
-
if (response && response.ok) {
|
|
118
|
-
const copy = response.clone();
|
|
119
|
-
caches.open(STATIC_CACHE).then((cache) => cache.put(request, copy));
|
|
120
|
-
}
|
|
121
|
-
return response;
|
|
122
|
-
});
|
|
123
|
-
}),
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* pi-web-ui — Progressive Web App service worker.
|
|
3
|
+
*
|
|
4
|
+
* Strategy overview
|
|
5
|
+
* -----------------
|
|
6
|
+
* pi-web-ui is a WebSocket-first app that needs a live backend, so we do NOT
|
|
7
|
+
* try to make it fully offline. Instead the SW focuses on what makes it a
|
|
8
|
+
* reliable *installable* PWA on mobile/desktop:
|
|
9
|
+
*
|
|
10
|
+
* - network-first for navigation requests (falls back to the cached app
|
|
11
|
+
* shell when the network flaps), and
|
|
12
|
+
* - cache-first for hashed static assets, which Vite fingerprints so a cache
|
|
13
|
+
* hit is always the right version until a new deploy publishes new hashes.
|
|
14
|
+
*
|
|
15
|
+
* Real-time / dynamic / credential-bearing routes (/ws, /api, /themes,
|
|
16
|
+
* /plugins) are always fetched from the network and never cached, so we never
|
|
17
|
+
* risk serving stale theme/plugin code or caching anything sensitive.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const STATIC_CACHE = "pi-web-ui-static-v1";
|
|
21
|
+
const SHELL_CACHE = "pi-web-ui-shell-v1";
|
|
22
|
+
|
|
23
|
+
// App root within this origin — "/" for root deployments, "/pi/" behind an
|
|
24
|
+
// nginx sub-path reverse proxy. All path checks below are relative to it, so
|
|
25
|
+
// the worker behaves identically under either deployment layout.
|
|
26
|
+
const SCOPE = new URL("./", self.registration.scope).pathname;
|
|
27
|
+
|
|
28
|
+
/** Map a request pathname to an app-relative path ("/pi/ws" → "/ws"), or null
|
|
29
|
+
* when the request lies outside the registration scope (shouldn't happen). */
|
|
30
|
+
function appPath(pathname) {
|
|
31
|
+
if (SCOPE === "/") return pathname;
|
|
32
|
+
if (pathname.startsWith(SCOPE)) return "/" + pathname.slice(SCOPE.length);
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
self.addEventListener("install", (event) => {
|
|
37
|
+
// Take control as soon as this version activates so the current page is
|
|
38
|
+
// served by the new worker without requiring a second reload.
|
|
39
|
+
self.skipWaiting();
|
|
40
|
+
event.waitUntil(caches.open(SHELL_CACHE));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
self.addEventListener("activate", (event) => {
|
|
44
|
+
event.waitUntil(
|
|
45
|
+
caches
|
|
46
|
+
.keys()
|
|
47
|
+
.then((keys) =>
|
|
48
|
+
Promise.all(keys.filter((k) => k !== STATIC_CACHE && k !== SHELL_CACHE).map((k) => caches.delete(k))),
|
|
49
|
+
)
|
|
50
|
+
// Apply to already-open pages immediately.
|
|
51
|
+
.then(() => self.clients.claim()),
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Only cache simple, safe GET requests. Everything else goes straight through.
|
|
56
|
+
function isCachable(request) {
|
|
57
|
+
const method = request.method;
|
|
58
|
+
if (method !== "GET") return false;
|
|
59
|
+
|
|
60
|
+
const url = new URL(request.url);
|
|
61
|
+
if (url.origin !== self.location.origin) return false;
|
|
62
|
+
|
|
63
|
+
// Never cache real-time, dynamic or credential/data endpoints.
|
|
64
|
+
const path = appPath(url.pathname);
|
|
65
|
+
if (
|
|
66
|
+
path === null ||
|
|
67
|
+
path.startsWith("/ws") ||
|
|
68
|
+
path.startsWith("/api") ||
|
|
69
|
+
path.startsWith("/themes") ||
|
|
70
|
+
path.startsWith("/plugins")
|
|
71
|
+
) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
self.addEventListener("fetch", (event) => {
|
|
78
|
+
const { request } = event;
|
|
79
|
+
if (!isCachable(request)) {
|
|
80
|
+
// Let the browser/backend handle WebSockets, API calls and cross-origin
|
|
81
|
+
// requests normally.
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const requestUrl = new URL(request.url);
|
|
86
|
+
|
|
87
|
+
// Navigation → app shell. Network-first with cached fallback: users get the
|
|
88
|
+
// latest build when online but can still reopen the app while flaky.
|
|
89
|
+
if (request.mode === "navigate") {
|
|
90
|
+
event.respondWith(
|
|
91
|
+
fetch(request)
|
|
92
|
+
.then((response) => {
|
|
93
|
+
const copy = response.clone();
|
|
94
|
+
caches.open(SHELL_CACHE).then((cache) => cache.put(request, copy));
|
|
95
|
+
return response;
|
|
96
|
+
})
|
|
97
|
+
.catch(() => caches.match(request).then((cached) => cached || caches.match(SCOPE) || Response.error())),
|
|
98
|
+
);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Static assets (hashed by Vite) → cache-first.
|
|
103
|
+
const path = appPath(requestUrl.pathname);
|
|
104
|
+
const isStatic =
|
|
105
|
+
path !== null &&
|
|
106
|
+
(path.startsWith("/assets/") ||
|
|
107
|
+
path.startsWith("/icons/") ||
|
|
108
|
+
path === "/favicon.svg" ||
|
|
109
|
+
path === "/icon.ico" ||
|
|
110
|
+
path === "/manifest.webmanifest");
|
|
111
|
+
|
|
112
|
+
if (isStatic) {
|
|
113
|
+
event.respondWith(
|
|
114
|
+
caches.match(request).then((cached) => {
|
|
115
|
+
if (cached) return cached;
|
|
116
|
+
return fetch(request).then((response) => {
|
|
117
|
+
if (response && response.ok) {
|
|
118
|
+
const copy = response.clone();
|
|
119
|
+
caches.open(STATIC_CACHE).then((cache) => cache.put(request, copy));
|
|
120
|
+
}
|
|
121
|
+
return response;
|
|
122
|
+
});
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
});
|
package/web/public/favicon.svg
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
-
<!-- pi symbol favicon: violet rounded square + white π (drawn as paths,
|
|
3
|
-
no font dependency) -->
|
|
4
|
-
<rect width="64" height="64" rx="14" fill="#8b5cf6"/>
|
|
5
|
-
<rect x="14" y="17" width="36" height="6.5" rx="3.25" fill="#ffffff"/>
|
|
6
|
-
<rect x="17.5" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
7
|
-
<rect x="40" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
8
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
2
|
+
<!-- pi symbol favicon: violet rounded square + white π (drawn as paths,
|
|
3
|
+
no font dependency) -->
|
|
4
|
+
<rect width="64" height="64" rx="14" fill="#8b5cf6"/>
|
|
5
|
+
<rect x="14" y="17" width="36" height="6.5" rx="3.25" fill="#ffffff"/>
|
|
6
|
+
<rect x="17.5" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
7
|
+
<rect x="40" y="23.5" width="6.5" height="25" rx="3.25" fill="#ffffff"/>
|
|
8
|
+
</svg>
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "pi-web-ui — pi coding agent",
|
|
3
|
-
"short_name": "pi-web-ui",
|
|
4
|
-
"description": "The polished browser cockpit for the pi coding agent. Stream conversations, inspect tool calls, manage files and run your workspace.",
|
|
5
|
-
"start_url": "./",
|
|
6
|
-
"scope": "./",
|
|
7
|
-
"display": "standalone",
|
|
8
|
-
"orientation": "any",
|
|
9
|
-
"background_color": "#0f172a",
|
|
10
|
-
"theme_color": "#0f172a",
|
|
11
|
-
"categories": ["developer tools", "productivity"],
|
|
12
|
-
"icons": [
|
|
13
|
-
{
|
|
14
|
-
"src": "./icons/icon-192.png",
|
|
15
|
-
"sizes": "192x192",
|
|
16
|
-
"type": "image/png",
|
|
17
|
-
"purpose": "any"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"src": "./icons/icon-512.png",
|
|
21
|
-
"sizes": "512x512",
|
|
22
|
-
"type": "image/png",
|
|
23
|
-
"purpose": "any"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"src": "./icons/icon-1024.png",
|
|
27
|
-
"sizes": "1024x1024",
|
|
28
|
-
"type": "image/png",
|
|
29
|
-
"purpose": "any"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"src": "./icons/maskable-192.png",
|
|
33
|
-
"sizes": "192x192",
|
|
34
|
-
"type": "image/png",
|
|
35
|
-
"purpose": "maskable"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"src": "./icons/maskable-512.png",
|
|
39
|
-
"sizes": "512x512",
|
|
40
|
-
"type": "image/png",
|
|
41
|
-
"purpose": "maskable"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"src": "./icons/maskable-1024.png",
|
|
45
|
-
"sizes": "1024x1024",
|
|
46
|
-
"type": "image/png",
|
|
47
|
-
"purpose": "maskable"
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-web-ui — pi coding agent",
|
|
3
|
+
"short_name": "pi-web-ui",
|
|
4
|
+
"description": "The polished browser cockpit for the pi coding agent. Stream conversations, inspect tool calls, manage files and run your workspace.",
|
|
5
|
+
"start_url": "./",
|
|
6
|
+
"scope": "./",
|
|
7
|
+
"display": "standalone",
|
|
8
|
+
"orientation": "any",
|
|
9
|
+
"background_color": "#0f172a",
|
|
10
|
+
"theme_color": "#0f172a",
|
|
11
|
+
"categories": ["developer tools", "productivity"],
|
|
12
|
+
"icons": [
|
|
13
|
+
{
|
|
14
|
+
"src": "./icons/icon-192.png",
|
|
15
|
+
"sizes": "192x192",
|
|
16
|
+
"type": "image/png",
|
|
17
|
+
"purpose": "any"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"src": "./icons/icon-512.png",
|
|
21
|
+
"sizes": "512x512",
|
|
22
|
+
"type": "image/png",
|
|
23
|
+
"purpose": "any"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"src": "./icons/icon-1024.png",
|
|
27
|
+
"sizes": "1024x1024",
|
|
28
|
+
"type": "image/png",
|
|
29
|
+
"purpose": "any"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"src": "./icons/maskable-192.png",
|
|
33
|
+
"sizes": "192x192",
|
|
34
|
+
"type": "image/png",
|
|
35
|
+
"purpose": "maskable"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"src": "./icons/maskable-512.png",
|
|
39
|
+
"sizes": "512x512",
|
|
40
|
+
"type": "image/png",
|
|
41
|
+
"purpose": "maskable"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"src": "./icons/maskable-1024.png",
|
|
45
|
+
"sizes": "1024x1024",
|
|
46
|
+
"type": "image/png",
|
|
47
|
+
"purpose": "maskable"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|