@firstpick/pi-package-webui 0.1.1 → 0.1.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.
Binary file
Binary file
Binary file
package/public/index.html CHANGED
@@ -2,9 +2,16 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
6
  <title>Pi Web UI</title>
7
+ <meta name="theme-color" content="#11111b" />
8
+ <meta name="mobile-web-app-capable" content="yes" />
9
+ <meta name="apple-mobile-web-app-capable" content="yes" />
10
+ <meta name="apple-mobile-web-app-title" content="Pi Web" />
11
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
12
+ <link rel="manifest" href="/manifest.webmanifest" />
7
13
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
14
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
8
15
  <link rel="stylesheet" href="/styles.css" />
9
16
  </head>
10
17
  <body>
@@ -18,11 +25,20 @@
18
25
  <main class="layout">
19
26
  <section class="chat-panel">
20
27
  <header class="terminal-tabs-shell">
21
- <div id="tabBar" class="terminal-tabs" role="tablist" aria-label="Pi terminal tabs"></div>
22
- <button id="newTabButton" class="terminal-new-tab-button" type="button" title="Start a separate isolated Pi terminal">+ Tab</button>
28
+ <button id="terminalTabsToggleButton" class="terminal-tabs-toggle-button" type="button" aria-controls="tabBar" aria-expanded="false">Tabs</button>
29
+ <div id="tabBar" class="terminal-tabs" role="tablist" aria-label="Pi terminal tabs">
30
+ <button id="newTabButton" class="terminal-new-tab-button" type="button" title="Start a separate isolated Pi terminal">+ Tab</button>
31
+ </div>
23
32
  </header>
24
33
  <div id="widgetArea" class="widget-area"></div>
25
- <div id="chat" class="chat" aria-live="polite"></div>
34
+ <div id="chat" class="chat" aria-live="polite">
35
+ <button id="stickyUserPromptButton" class="sticky-user-prompt-button" type="button" aria-controls="chat" hidden></button>
36
+ </div>
37
+ <div id="feedbackTray" class="feedback-tray" aria-live="polite" hidden>
38
+ <span id="feedbackTraySummary">No action feedback queued.</span>
39
+ <button id="sendFeedbackButton" type="button">Send &amp; create LEARNING</button>
40
+ </div>
41
+ <button id="jumpToLatestButton" class="jump-to-latest-button" type="button" hidden>Latest ↓</button>
26
42
  <div id="statusBar" class="statusbar" aria-live="polite"></div>
27
43
  <section id="gitWorkflowPanel" class="git-workflow-panel" aria-live="polite" hidden>
28
44
  <div class="git-workflow-header">
@@ -38,34 +54,50 @@
38
54
  <div id="gitWorkflowActions" class="git-workflow-actions"></div>
39
55
  </section>
40
56
  <form id="composer" class="composer">
41
- <textarea id="promptInput" rows="4" placeholder="Ask Pi…"></textarea>
42
- <div id="commandSuggest" class="command-suggest" role="listbox" aria-label="Command suggestions" hidden></div>
57
+ <textarea id="promptInput" rows="1" enterkeyhint="enter" placeholder="Ask Pi…" autofocus></textarea>
58
+ <div id="commandSuggest" class="command-suggest" role="listbox" aria-label="Command and path suggestions" hidden></div>
43
59
  <div class="composer-row">
44
- <label>
45
- Busy prompt behavior
46
- <select id="busyBehavior">
47
- <option value="followUp">follow-up</option>
48
- <option value="steer">steer</option>
49
- </select>
50
- </label>
60
+ <button id="composerActionsButton" class="composer-actions-button" type="button" aria-controls="composerActionsPanel" aria-expanded="false">Actions</button>
61
+ <div id="composerActionsPanel" class="composer-actions-panel" aria-label="Composer actions">
62
+ <label>
63
+ Busy prompt behavior
64
+ <select id="busyBehavior">
65
+ <option value="followUp">follow-up</option>
66
+ <option value="steer">steer</option>
67
+ </select>
68
+ </label>
69
+ <button id="newSessionButton" class="composer-new-button" type="button">New</button>
70
+ <button id="compactButton" class="composer-compact-button" type="button" title="Compact the current Pi session context">Compact</button>
71
+ <button
72
+ id="gitWorkflowButton"
73
+ class="composer-git-button"
74
+ type="button"
75
+ title="Guided Git workflow: git add ., /git-staged-msg, preview messages, commit short/long, git push. Cancel is available at each step."
76
+ aria-label="Start guided Git workflow: git add dot, run git-staged-msg, preview messages, commit short or long, then git push. Cancel is available at each step."
77
+ data-tooltip="Guided Git workflow:&#10;1. Run git add .&#10;2. Run /git-staged-msg&#10;3. Preview short + long messages&#10;4. Commit with short or long message&#10;5. Run git push&#10;Cancel is available at each step."
78
+ >Git workflow</button>
79
+ </div>
51
80
  <div class="spacer"></div>
52
- <button id="newSessionButton" class="composer-new-button" type="button">New</button>
53
- <button id="compactButton" class="composer-compact-button" type="button" title="Compact the current Pi session context">Compact</button>
54
81
  <button
55
- id="gitWorkflowButton"
56
- class="composer-git-button"
82
+ id="steerButton"
57
83
  type="button"
58
- title="Guided Git workflow: git add ., /git-staged-msg, preview messages, commit short/long, git push. Cancel is available at each step."
59
- aria-label="Start guided Git workflow: git add dot, run git-staged-msg, preview messages, commit short or long, then git push. Cancel is available at each step."
60
- data-tooltip="Guided Git workflow:&#10;1. Run git add .&#10;2. Run /git-staged-msg&#10;3. Preview short + long messages&#10;4. Commit with short or long message&#10;5. Run git push&#10;Cancel is available at each step."
61
- >Git workflow</button>
62
- <button id="steerButton" type="button">Steer</button>
63
- <button id="followUpButton" type="button">Follow-up</button>
64
- <button type="submit" class="primary">Send</button>
84
+ title="Type your message first, then tap Steer to guide the active Pi run without sending a normal prompt. Use it for corrections or direction changes while Pi is working."
85
+ aria-label="Steer: type your message first, then tap this button to guide the active Pi run."
86
+ data-tooltip="Steer usage:&#10;1. Type your steering message in the textarea.&#10;2. Tap Steer to guide the active Pi run.&#10;Use for corrections or direction changes while Pi is working."
87
+ >Steer</button>
88
+ <button
89
+ id="followUpButton"
90
+ type="button"
91
+ title="Type your message first, then tap Follow-up to send it as a follow-up instead of a normal prompt. Use it to add extra context or the next request."
92
+ aria-label="Follow-up: type your message first, then tap this button to send it as a follow-up."
93
+ data-tooltip="Follow-up usage:&#10;1. Type your message in the textarea.&#10;2. Tap Follow-up to send it as a follow-up.&#10;Use for extra context or the next request."
94
+ >Follow-up</button>
95
+ <button id="sendButton" type="submit" class="primary">Send</button>
65
96
  </div>
66
97
  </form>
67
98
  </section>
68
99
 
100
+ <button id="sidePanelBackdrop" class="side-panel-backdrop" type="button" aria-label="Close side panel" hidden></button>
69
101
  <aside id="sidePanel" class="side-panel">
70
102
  <div class="side-panel-header">
71
103
  <div>
@@ -100,6 +132,10 @@
100
132
  </select>
101
133
  <button id="setThinkingButton" type="button">Set thinking</button>
102
134
  </div>
135
+ <div class="control-field">
136
+ <label for="themeSelect">Theme</label>
137
+ <select id="themeSelect" title="Theme"></select>
138
+ </div>
103
139
  <div class="control-field network-control-field">
104
140
  <label>Network</label>
105
141
  <div id="networkStatus" class="network-status closed">Local only</div>
@@ -0,0 +1,40 @@
1
+ {
2
+ "id": "/",
3
+ "name": "Pi Web UI",
4
+ "short_name": "Pi Web",
5
+ "description": "Mobile-friendly web interface for Pi coding agent sessions.",
6
+ "start_url": "/",
7
+ "scope": "/",
8
+ "display": "standalone",
9
+ "display_override": ["window-controls-overlay", "standalone", "minimal-ui", "browser"],
10
+ "background_color": "#11111b",
11
+ "theme_color": "#11111b",
12
+ "orientation": "any",
13
+ "categories": ["developer", "productivity", "utilities"],
14
+ "icons": [
15
+ {
16
+ "src": "/favicon.svg",
17
+ "sizes": "any",
18
+ "type": "image/svg+xml",
19
+ "purpose": "any"
20
+ },
21
+ {
22
+ "src": "/apple-touch-icon.png",
23
+ "sizes": "180x180",
24
+ "type": "image/png",
25
+ "purpose": "any"
26
+ },
27
+ {
28
+ "src": "/icon-192.png",
29
+ "sizes": "192x192",
30
+ "type": "image/png",
31
+ "purpose": "any maskable"
32
+ },
33
+ {
34
+ "src": "/icon-512.png",
35
+ "sizes": "512x512",
36
+ "type": "image/png",
37
+ "purpose": "any maskable"
38
+ }
39
+ ]
40
+ }
@@ -0,0 +1,58 @@
1
+ const CACHE_NAME = "pi-webui-pwa-v6";
2
+ const APP_SHELL = [
3
+ "/",
4
+ "/index.html",
5
+ "/styles.css",
6
+ "/app.js",
7
+ "/favicon.svg",
8
+ "/apple-touch-icon.png",
9
+ "/icon-192.png",
10
+ "/icon-512.png",
11
+ "/manifest.webmanifest",
12
+ ];
13
+
14
+ self.addEventListener("install", (event) => {
15
+ event.waitUntil(caches.open(CACHE_NAME).then((cache) => cache.addAll(APP_SHELL)).then(() => self.skipWaiting()));
16
+ });
17
+
18
+ self.addEventListener("activate", (event) => {
19
+ event.waitUntil(
20
+ caches.keys()
21
+ .then((keys) => Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))))
22
+ .then(() => self.clients.claim()),
23
+ );
24
+ });
25
+
26
+ self.addEventListener("notificationclick", (event) => {
27
+ event.notification.close();
28
+ const targetUrl = event.notification.data?.url || `${self.location.origin}/`;
29
+ event.waitUntil(
30
+ self.clients.matchAll({ type: "window", includeUncontrolled: true }).then((clients) => {
31
+ const webuiClient = clients.find((client) => client.url.startsWith(self.location.origin));
32
+ if (webuiClient) return webuiClient.focus();
33
+ return self.clients.openWindow?.(targetUrl);
34
+ }),
35
+ );
36
+ });
37
+
38
+ self.addEventListener("fetch", (event) => {
39
+ const { request } = event;
40
+ if (request.method !== "GET") return;
41
+
42
+ const url = new URL(request.url);
43
+ if (url.origin !== self.location.origin || url.pathname.startsWith("/api/")) return;
44
+
45
+ if (request.mode === "navigate") {
46
+ event.respondWith(fetch(request).catch(() => caches.match("/index.html")));
47
+ return;
48
+ }
49
+
50
+ if (!APP_SHELL.includes(url.pathname)) return;
51
+ event.respondWith(
52
+ caches.match(request).then((cached) => cached || fetch(request).then((response) => {
53
+ const copy = response.clone();
54
+ caches.open(CACHE_NAME).then((cache) => cache.put(request, copy));
55
+ return response;
56
+ })),
57
+ );
58
+ });