@timqi/pier 0.0.29 → 0.1.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/README.md +58 -125
- package/dist/agent/config.js +24 -11
- package/dist/agent/credentials.js +11 -23
- package/dist/agent/events.js +43 -62
- package/dist/agent/listing.js +113 -68
- package/dist/agent/pi.js +204 -211
- package/dist/boards/boards.js +19 -29
- package/dist/channels/attach.js +14 -42
- package/dist/channels/chains.js +33 -37
- package/dist/channels/chunk.js +8 -28
- package/dist/channels/commands.js +3 -14
- package/dist/channels/config.js +33 -52
- package/dist/channels/control.js +4 -13
- package/dist/channels/conversations.js +8 -25
- package/dist/channels/dedup.js +8 -17
- package/dist/channels/gatekeeper.js +13 -23
- package/dist/channels/lark-api.js +23 -63
- package/dist/channels/lark-outbound.js +12 -44
- package/dist/channels/lark-panel.js +8 -24
- package/dist/channels/lark-render.js +18 -62
- package/dist/channels/lark.js +52 -141
- package/dist/channels/lines.js +13 -15
- package/dist/channels/panel.js +16 -36
- package/dist/channels/receipts.js +29 -52
- package/dist/channels/routes.js +3 -9
- package/dist/channels/runtime.js +12 -23
- package/dist/channels/slack-api.js +34 -86
- package/dist/channels/slack-directory.js +7 -23
- package/dist/channels/slack-outbound.js +12 -56
- package/dist/channels/slack-panel.js +4 -13
- package/dist/channels/slack-render.js +23 -91
- package/dist/channels/slack-tool.js +48 -171
- package/dist/channels/slack.js +73 -239
- package/dist/channels/telegram-api.js +8 -20
- package/dist/channels/telegram-panel.js +5 -21
- package/dist/channels/telegram-render.js +13 -40
- package/dist/channels/telegram.js +54 -146
- package/dist/channels/types.js +5 -16
- package/dist/cli.js +17 -41
- package/dist/config-sync.js +87 -4
- package/dist/core/hub.js +7 -20
- package/dist/core/identity.js +20 -59
- package/dist/core/inbound-file.js +15 -49
- package/dist/core/inbox.js +13 -35
- package/dist/core/queue.js +3 -5
- package/dist/core/reply.js +41 -142
- package/dist/core/router.js +209 -260
- package/dist/core/types.js +17 -1
- package/dist/db.js +98 -252
- package/dist/drain.js +58 -51
- package/dist/extensions/index.js +3 -11
- package/dist/extensions/web/anthropic.js +3 -9
- package/dist/extensions/web/artifacts.js +2 -5
- package/dist/extensions/web/content.js +6 -14
- package/dist/extensions/web/http.js +2 -6
- package/dist/extensions/web/language.js +8 -18
- package/dist/extensions/web/openai.js +1 -1
- package/dist/extensions/web/provider.js +5 -18
- package/dist/extensions/web/tools.js +19 -63
- package/dist/lock.js +98 -0
- package/dist/log.js +9 -26
- package/dist/main.js +87 -179
- package/dist/paths.js +10 -26
- package/dist/secrets.js +19 -46
- package/dist/service.js +33 -75
- package/dist/settings.js +42 -65
- package/dist/tasks/agent.js +129 -114
- package/dist/tasks/callbacks.js +9 -19
- package/dist/tasks/command.js +29 -14
- package/dist/tasks/definitions.js +39 -62
- package/dist/tasks/execution.js +46 -42
- package/dist/tasks/groups.js +41 -35
- package/dist/tasks/messages.js +121 -182
- package/dist/tasks/outbox.js +61 -55
- package/dist/tasks/routes.js +5 -11
- package/dist/tasks/runs.js +14 -13
- package/dist/tasks/service.js +53 -54
- package/dist/tasks/store.js +53 -30
- package/dist/tasks/tool.js +132 -61
- package/dist/tools-task.js +20 -60
- package/dist/tools.js +100 -327
- package/dist/update.js +21 -44
- package/dist/web/auth.js +118 -179
- package/dist/web/config-sync.js +2 -2
- package/dist/web/config.js +3 -7
- package/dist/web/explorer.js +10 -21
- package/dist/web/fs.js +20 -42
- package/dist/web/instance.js +45 -85
- package/dist/web/providers.js +14 -13
- package/dist/web/public/assets/{activity-D3m4L2IL.js → activity-B89_hH7q.js} +2 -2
- package/dist/web/public/assets/activity-B89_hH7q.js.br +0 -0
- package/dist/web/public/assets/activity-B89_hH7q.js.gz +0 -0
- package/dist/web/public/assets/boards-BeKW0ZXK.js +1 -0
- package/dist/web/public/assets/boards-BeKW0ZXK.js.br +0 -0
- package/dist/web/public/assets/boards-BeKW0ZXK.js.gz +0 -0
- package/dist/web/public/assets/explorer-DIuMlaV3.js +4 -0
- package/dist/web/public/assets/explorer-DIuMlaV3.js.br +0 -0
- package/dist/web/public/assets/explorer-DIuMlaV3.js.gz +0 -0
- package/dist/web/public/assets/index-DzXDXra_.js +85 -0
- package/dist/web/public/assets/index-DzXDXra_.js.br +0 -0
- package/dist/web/public/assets/index-DzXDXra_.js.gz +0 -0
- package/dist/web/public/assets/index-eqQLVS8Q.css +2 -0
- package/dist/web/public/assets/index-eqQLVS8Q.css.br +0 -0
- package/dist/web/public/assets/index-eqQLVS8Q.css.gz +0 -0
- package/dist/web/public/assets/runs-Cwy0mN8i.js +1 -0
- package/dist/web/public/assets/runs-Cwy0mN8i.js.br +0 -0
- package/dist/web/public/assets/runs-Cwy0mN8i.js.gz +0 -0
- package/dist/web/public/assets/settings-DzZLmujq.js +5 -0
- package/dist/web/public/assets/settings-DzZLmujq.js.br +0 -0
- package/dist/web/public/assets/settings-DzZLmujq.js.gz +0 -0
- package/dist/web/public/assets/task-runs-BCakxFk8.js +3 -0
- package/dist/web/public/assets/task-runs-BCakxFk8.js.br +0 -0
- package/dist/web/public/assets/task-runs-BCakxFk8.js.gz +0 -0
- package/dist/web/public/assets/tasks-BlzEbk11.js +4 -0
- package/dist/web/public/assets/tasks-BlzEbk11.js.br +0 -0
- package/dist/web/public/assets/tasks-BlzEbk11.js.gz +0 -0
- package/dist/web/public/index.html +100 -130
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/manifest.webmanifest +2 -2
- package/dist/web/public/manifest.webmanifest.br +0 -0
- package/dist/web/public/manifest.webmanifest.gz +0 -0
- package/dist/web/public/sw.js +14 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/push.js +55 -77
- package/dist/web/route.js +3 -7
- package/dist/web/server.js +131 -180
- package/dist/web/session-state.js +14 -54
- package/dist/web/types.js +2 -4
- package/dist/web/webpush.js +10 -25
- package/docs/deploy.md +115 -330
- package/package.json +2 -1
- package/skills/pier-boards/SKILL.md +81 -160
- package/skills/pier-help/SKILL.md +23 -20
- package/skills/pier-slack/SKILL.md +2 -2
- package/skills/pier-tasks/SKILL.md +153 -160
- package/dist/config-sync-fetch.js +0 -84
- package/dist/limits.js +0 -14
- package/dist/web/public/assets/activity-D3m4L2IL.js.br +0 -0
- package/dist/web/public/assets/activity-D3m4L2IL.js.gz +0 -0
- package/dist/web/public/assets/boards-BIObcQeX.js +0 -1
- package/dist/web/public/assets/boards-BIObcQeX.js.br +0 -0
- package/dist/web/public/assets/boards-BIObcQeX.js.gz +0 -0
- package/dist/web/public/assets/explorer-C_rSWPNB.js +0 -4
- package/dist/web/public/assets/explorer-C_rSWPNB.js.br +0 -0
- package/dist/web/public/assets/explorer-C_rSWPNB.js.gz +0 -0
- package/dist/web/public/assets/index-CX3fYZY5.css +0 -2
- package/dist/web/public/assets/index-CX3fYZY5.css.br +0 -0
- package/dist/web/public/assets/index-CX3fYZY5.css.gz +0 -0
- package/dist/web/public/assets/index-uFsZkKOQ.js +0 -85
- package/dist/web/public/assets/index-uFsZkKOQ.js.br +0 -0
- package/dist/web/public/assets/index-uFsZkKOQ.js.gz +0 -0
- package/dist/web/public/assets/runs-Ch6DZq6O.js +0 -1
- package/dist/web/public/assets/runs-Ch6DZq6O.js.br +0 -0
- package/dist/web/public/assets/runs-Ch6DZq6O.js.gz +0 -0
- package/dist/web/public/assets/settings-BWcEIEcv.js +0 -5
- package/dist/web/public/assets/settings-BWcEIEcv.js.br +0 -0
- package/dist/web/public/assets/settings-BWcEIEcv.js.gz +0 -0
- package/dist/web/public/assets/task-runs-DPkwv2UE.js +0 -3
- package/dist/web/public/assets/task-runs-DPkwv2UE.js.br +0 -0
- package/dist/web/public/assets/task-runs-DPkwv2UE.js.gz +0 -0
- package/dist/web/public/assets/tasks-DTiCi2mH.js +0 -4
- package/dist/web/public/assets/tasks-DTiCi2mH.js.br +0 -0
- package/dist/web/public/assets/tasks-DTiCi2mH.js.gz +0 -0
|
@@ -7,17 +7,19 @@
|
|
|
7
7
|
workbench zoomed by a stray gesture has no visible way back — said again
|
|
8
8
|
as `touch-action` (style.css) for the engines that ignore this pair. -->
|
|
9
9
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
|
|
10
|
-
<meta name="theme-color" content="#
|
|
10
|
+
<meta name="theme-color" content="#f1f4f3" />
|
|
11
11
|
<!-- Ahead of the stylesheet, because a workbench that flashes white and then
|
|
12
12
|
goes dark reads as a bug. This is the only place "system" is resolved
|
|
13
13
|
before the bundle exists; theme.ts owns the choice from there on. -->
|
|
14
14
|
<script>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
var t;
|
|
16
|
+
try { t = localStorage.getItem("pier.theme"); }
|
|
17
|
+
catch (e) { /* storage denied: follow the system for this visit */ }
|
|
18
|
+
var mode = t === "light" || t === "dark" ? t
|
|
19
|
+
: matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
20
|
+
document.documentElement.dataset.theme = mode;
|
|
21
|
+
// Before CSS loads, mirror its canvas token so installed chrome never flashes.
|
|
22
|
+
document.querySelector('meta[name="theme-color"]').content = mode === "dark" ? "#14171a" : "#f1f4f3";
|
|
21
23
|
</script>
|
|
22
24
|
<!-- Installed as a home-screen app: standalone window, own icon. The
|
|
23
25
|
manifest shares the workbench's cookie boundary. -->
|
|
@@ -35,8 +37,8 @@
|
|
|
35
37
|
which style.css pays for with the safe-area inset. -->
|
|
36
38
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
37
39
|
<title>Pier</title>
|
|
38
|
-
<script type="module" crossorigin src="/assets/index-
|
|
39
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
40
|
+
<script type="module" crossorigin src="/assets/index-DzXDXra_.js"></script>
|
|
41
|
+
<link rel="stylesheet" crossorigin href="/assets/index-eqQLVS8Q.css">
|
|
40
42
|
</head>
|
|
41
43
|
<!-- The document never scrolls: this is a fixed-viewport workbench, and every
|
|
42
44
|
scrollable region is an inner pane. h-dvh, not h-screen, because 100vh can
|
|
@@ -52,11 +54,9 @@
|
|
|
52
54
|
control in the same band. -->
|
|
53
55
|
<button type="button" id="rail-toggle" aria-label="Toggle sidebar"
|
|
54
56
|
class="fixed top-1.5 z-40 hidden h-7 w-7 cursor-pointer items-center justify-center rounded-md text-neutral-400 hover:bg-neutral-200 hover:text-neutral-700 md:flex">
|
|
55
|
-
<
|
|
56
|
-
<path d="M9.5 4 5.5 8l4 4" stroke-linecap="round" stroke-linejoin="round" />
|
|
57
|
-
</svg>
|
|
57
|
+
<span data-icon="ChevronLeft" class="h-3.5 w-3.5"></span>
|
|
58
58
|
</button>
|
|
59
|
-
<aside id="sidebar" class="flex flex-col overflow-hidden border-r border-neutral-200 bg-neutral-50">
|
|
59
|
+
<aside id="sidebar" class="flex flex-col overflow-hidden border-r border-neutral-200 bg-neutral-50 font-sans">
|
|
60
60
|
<header class="flex h-12 flex-none items-center gap-2 px-3">
|
|
61
61
|
<!-- The same mark as the tab and the home-screen icon, so an installed
|
|
62
62
|
Pier looks like the thing you installed. -->
|
|
@@ -76,72 +76,59 @@
|
|
|
76
76
|
<button type="button" id="theme-toggle" aria-label="Theme"
|
|
77
77
|
class="icon-btn text-[13px]"></button>
|
|
78
78
|
</header>
|
|
79
|
+
<div class="flex flex-none items-center gap-1.5 px-3 pb-1">
|
|
80
|
+
<button type="button" id="new-session" aria-label="New session"
|
|
81
|
+
class="btn btn-primary flex min-w-0 flex-1 items-center justify-center gap-2 whitespace-nowrap px-3">
|
|
82
|
+
<span data-icon="Plus" aria-hidden="true" class="h-3.5 w-3.5"></span> New session
|
|
83
|
+
</button>
|
|
84
|
+
<button type="button" id="open-palette" aria-label="Search sessions, messages and Console"
|
|
85
|
+
class="btn flex h-8 w-8 flex-none items-center justify-center bg-neutral-100 p-0 text-neutral-600 hover:bg-neutral-200 active:bg-neutral-300">
|
|
86
|
+
<span data-icon="Search" class="h-5 w-5 flex-none"></span>
|
|
87
|
+
<span class="sr-only">Search</span>
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
79
90
|
<details id="console-section" open class="flex-none border-b border-neutral-200/70">
|
|
80
|
-
<summary class="flex cursor-pointer select-none items-center gap-1 px-3
|
|
81
|
-
<
|
|
91
|
+
<summary class="flex cursor-pointer select-none items-center gap-1 px-3 py-1 text-xs font-semibold leading-5 text-neutral-500 hover:bg-neutral-100">
|
|
92
|
+
<span data-icon="ChevronRight" class="chev h-3 w-3"></span>Console
|
|
82
93
|
</summary>
|
|
83
|
-
<ul class="pb-
|
|
94
|
+
<ul class="pb-1">
|
|
84
95
|
<!-- One row for the tasks area: Tasks, Runs and Activity are tabs of
|
|
85
96
|
the Automation page (views.ts), not three sidebar entries. -->
|
|
86
97
|
<li><button type="button" id="open-tasks"
|
|
87
|
-
class="flex w-full cursor-pointer items-center gap-2
|
|
88
|
-
<
|
|
89
|
-
<path d="M6 3h8M6 8h8M6 13h8M2 3h1M2 8h1M2 13h1" />
|
|
90
|
-
</svg>Automation</button></li>
|
|
98
|
+
class="flex w-full cursor-pointer items-center gap-2 pr-3 text-left hover:bg-neutral-100">
|
|
99
|
+
<span data-icon="ListTodo" class="h-3.5 w-3.5 flex-none text-neutral-400"></span>Automation</button></li>
|
|
91
100
|
<li><button type="button" id="open-boards"
|
|
92
|
-
class="flex w-full cursor-pointer items-center gap-2
|
|
93
|
-
<
|
|
94
|
-
<rect x="2" y="2" width="12" height="12" rx="1.5" /><path d="M2 6.5h12M6.5 6.5V14" />
|
|
95
|
-
</svg>Boards</button></li>
|
|
101
|
+
class="flex w-full cursor-pointer items-center gap-2 pr-3 text-left hover:bg-neutral-100">
|
|
102
|
+
<span data-icon="LayoutDashboard" class="h-3.5 w-3.5 flex-none text-neutral-400"></span>Boards</button></li>
|
|
96
103
|
<li><button type="button" id="open-settings"
|
|
97
|
-
class="flex w-full cursor-pointer items-center gap-2
|
|
98
|
-
<
|
|
99
|
-
<!-- Teeth every 60° about (8,8); the hub is that same centre. -->
|
|
100
|
-
<path d="M6.8 2.2h2.4l.32 1.6a4.9 4.9 0 0 1 1.36.79l1.55-.53 1.2 2.08-1.23 1.07a4.9 4.9 0 0 1 0 1.58l1.23 1.07-1.2 2.08-1.55-.53a4.9 4.9 0 0 1-1.36.79l-.32 1.6H6.8l-.32-1.6a4.9 4.9 0 0 1-1.36-.79l-1.55.53-1.2-2.08 1.23-1.07a4.9 4.9 0 0 1 0-1.58L2.37 6.14l1.2-2.08 1.55.53a4.9 4.9 0 0 1 1.36-.79z" stroke-linejoin="round" />
|
|
101
|
-
<circle cx="8" cy="8" r="1.9" />
|
|
102
|
-
</svg>Settings</button></li>
|
|
104
|
+
class="flex w-full cursor-pointer items-center gap-2 pr-3 text-left hover:bg-neutral-100">
|
|
105
|
+
<span data-icon="Settings" class="h-3.5 w-3.5 flex-none text-neutral-400"></span>Settings</button></li>
|
|
103
106
|
</ul>
|
|
104
107
|
</details>
|
|
105
|
-
<div class="flex
|
|
106
|
-
|
|
107
|
-
<button type="button" id="open-archive"
|
|
108
|
-
class="icon-btn ml-auto" aria-label="Search sessions and Console">
|
|
109
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5">
|
|
110
|
-
<circle cx="7" cy="7" r="4.25" /><path d="M10.2 10.2 14 14" stroke-linecap="round" />
|
|
111
|
-
</svg>
|
|
112
|
-
</button>
|
|
113
|
-
<button type="button" id="new-session" title="New session"
|
|
114
|
-
class="icon-btn" aria-label="New session">
|
|
115
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5">
|
|
116
|
-
<rect x="2.25" y="2.25" width="11.5" height="11.5" rx="2.5" />
|
|
117
|
-
<path d="M8 5.5v5M5.5 8h5" stroke-linecap="round" />
|
|
118
|
-
</svg>
|
|
119
|
-
</button>
|
|
120
|
-
</div>
|
|
121
|
-
<div id="session-list" class="flex-1 overflow-y-auto text-[13.5px]"></div>
|
|
108
|
+
<div class="flex-none px-3 pb-1 pt-2 text-xs font-semibold leading-5 text-neutral-500">Sessions</div>
|
|
109
|
+
<div id="session-list" class="min-h-0 flex-1 overflow-y-auto"></div>
|
|
122
110
|
</aside>
|
|
123
111
|
|
|
124
|
-
<main class="
|
|
112
|
+
<main class="min-w-0 overflow-hidden">
|
|
125
113
|
<!-- Mobile top bar: replaces the chat header below md (which hides), so a
|
|
126
114
|
Console view keeps the same way back to the drawer as a chat does. -->
|
|
127
|
-
<header id="mobile-bar" class="flex
|
|
115
|
+
<header id="mobile-bar" class="flex flex-none items-center gap-1 px-1.5 md:hidden">
|
|
128
116
|
<button type="button" id="drawer-toggle" aria-label="Open sidebar"
|
|
129
|
-
class="relative
|
|
130
|
-
<
|
|
131
|
-
<path d="M2.5 4h11M2.5 8h11M2.5 12h11" />
|
|
132
|
-
</svg>
|
|
117
|
+
class="icon-btn relative h-11 w-11 text-neutral-500">
|
|
118
|
+
<span data-icon="Menu" class="h-4.5 w-4.5"></span>
|
|
133
119
|
</button>
|
|
134
120
|
<span id="mobile-title" class="min-w-0 flex-1 truncate text-[16px] font-medium"></span>
|
|
121
|
+
<!-- Both bar controls are the shared round icon button at a thumb's size
|
|
122
|
+
(44px), with the chat header's own 14px ⋯ glyph — not a row of
|
|
123
|
+
oversized dots. -->
|
|
135
124
|
<button type="button" id="mobile-menu" aria-label="Session actions"
|
|
136
|
-
class="hidden h-
|
|
125
|
+
class="icon-btn hidden h-11 w-11"><span data-icon="Ellipsis" class="h-3.5 w-3.5"></span></button>
|
|
137
126
|
</header>
|
|
138
|
-
<!-- Automation hosts three views under one title and
|
|
139
|
-
|
|
127
|
+
<!-- Automation hosts three views under one head — title, tabs and the
|
|
128
|
+
page's primary action on one strip, drawn by views.ts; its active pill
|
|
129
|
+
tracks the route (#/tasks, #/runs, #/activity). -->
|
|
140
130
|
<section id="automation-view" class="hidden min-h-0 flex-1 flex-col">
|
|
141
|
-
<header
|
|
142
|
-
<span class="font-medium">Automation</span>
|
|
143
|
-
</header>
|
|
144
|
-
<div id="automation-tabs" class="tabstrip bg-white"></div>
|
|
131
|
+
<header id="automation-tabs" class="pagehead"></header>
|
|
145
132
|
<section id="tasks-view" class="hidden min-h-0 flex-1 flex-col"></section>
|
|
146
133
|
<section id="runs-view" class="hidden min-h-0 flex-1 flex-col"></section>
|
|
147
134
|
<section id="activity-view" class="hidden min-h-0 flex-1 flex-col"></section>
|
|
@@ -157,7 +144,7 @@
|
|
|
157
144
|
<!-- Inline session meta: model · reasoning · current context size. -->
|
|
158
145
|
<div id="session-meta" class="hidden flex-none items-center gap-1 text-[11px]"></div>
|
|
159
146
|
<button type="button" id="chat-menu" title="Session actions" aria-label="Session actions"
|
|
160
|
-
class="icon-btn"
|
|
147
|
+
class="icon-btn"><span data-icon="Ellipsis" class="h-3.5 w-3.5"></span></button>
|
|
161
148
|
</div>
|
|
162
149
|
</header>
|
|
163
150
|
<!-- The transcript's own type scale, inherited by rows, chips and markdown. -->
|
|
@@ -166,36 +153,21 @@
|
|
|
166
153
|
<div id="turns" data-gallery class="flex-1 overflow-y-auto pb-5 pt-2 text-[15px] leading-[1.55]"></div>
|
|
167
154
|
<!-- Pi's queue primitives are whole-queue (steer / clear), so the actions
|
|
168
155
|
live on the header row and read as "the queue", never per message. -->
|
|
169
|
-
<div id="queue-panel" class="hidden flex-col border-t border-neutral-200 px-3
|
|
156
|
+
<div id="queue-panel" class="hidden flex-col border-t border-neutral-200 px-4 pb-3 pt-2">
|
|
170
157
|
<div class="flex h-7 items-center gap-2">
|
|
171
158
|
<span id="queue-label" class="text-[11px] font-semibold uppercase tracking-wide text-amber-700">Queued</span>
|
|
172
159
|
<div class="ml-auto flex items-center gap-0.5 text-amber-700">
|
|
173
160
|
<button type="button" id="queue-steer" title="Send the whole queue now into the running turn" aria-label="Send queue now"
|
|
174
161
|
class="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-amber-100 active:bg-amber-200">
|
|
175
|
-
<
|
|
176
|
-
stroke-linecap="round" stroke-linejoin="round" class="h-3.5 w-3.5">
|
|
177
|
-
<path d="M14.5 1.5 7 9m7.5-7.5-4.2 12.6L7 9 1.7 6.7l12.8-5.2z" />
|
|
178
|
-
</svg>
|
|
162
|
+
<span data-icon="ArrowUp" class="h-3.5 w-3.5"></span>
|
|
179
163
|
</button>
|
|
180
164
|
<button type="button" id="queue-restart" title="Stop the running turn and send the whole queue as a new prompt" aria-label="Stop and send queue"
|
|
181
165
|
class="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-amber-100 active:bg-amber-200">
|
|
182
|
-
<
|
|
183
|
-
stroke-linecap="round" stroke-linejoin="round" class="h-3.5 w-3.5">
|
|
184
|
-
<!-- The arc's ink sits high-right of the box; centre it so the
|
|
185
|
-
three icons share one baseline. -->
|
|
186
|
-
<g transform="translate(-0.8 1.9)">
|
|
187
|
-
<path d="M13 5.2V1.8m0 0H9.6M13 1.8A6 6 0 1 0 14 9" />
|
|
188
|
-
<path d="M6.2 8h4M8.5 5.7 10.8 8l-2.3 2.3" />
|
|
189
|
-
</g>
|
|
190
|
-
</svg>
|
|
166
|
+
<span data-icon="RotateCw" class="h-3.5 w-3.5"></span>
|
|
191
167
|
</button>
|
|
192
168
|
<button type="button" id="queue-recall" title="Return queued messages to the composer" aria-label="Recall queued messages"
|
|
193
169
|
class="flex h-7 w-7 cursor-pointer items-center justify-center rounded-md hover:bg-amber-100 active:bg-amber-200">
|
|
194
|
-
<
|
|
195
|
-
stroke-linecap="round" stroke-linejoin="round" class="h-3.5 w-3.5">
|
|
196
|
-
<!-- Ink centred on the 16×16 box, or the glyph sits low next to its neighbours. -->
|
|
197
|
-
<path d="M5 3 2 6l3 3M2.5 6H10a3.5 3.5 0 0 1 0 7H8" />
|
|
198
|
-
</svg>
|
|
170
|
+
<span data-icon="Undo2" class="h-3.5 w-3.5"></span>
|
|
199
171
|
</button>
|
|
200
172
|
</div>
|
|
201
173
|
</div>
|
|
@@ -203,75 +175,60 @@
|
|
|
203
175
|
(18px leading) rather than shrinking the turns pane any further. -->
|
|
204
176
|
<ul id="queue-rows" class="flex max-h-[6rem] flex-col gap-1 overflow-y-auto overscroll-contain"></ul>
|
|
205
177
|
</div>
|
|
206
|
-
<form id="composer" class="flex-none px-4 pb-
|
|
178
|
+
<form id="composer" class="flex-none px-4 pb-4 pt-2">
|
|
207
179
|
<div class="glass rounded-[1.75rem] border border-neutral-200 px-3 py-2.5 transition-shadow focus-within:border-indigo-400">
|
|
208
180
|
<div id="image-strip" data-gallery class="hidden flex-wrap gap-2 px-1 pb-1.5 pt-1"></div>
|
|
209
181
|
<!-- items-end keeps the icons on the bottom row while the textarea grows upward -->
|
|
210
182
|
<div class="flex items-end gap-1.5">
|
|
211
183
|
<button type="button" id="attach" title="Attach file (or paste / drop)"
|
|
212
|
-
class="flex h-7 w-7 flex-none cursor-pointer items-center justify-center rounded-lg text-[17px] leading-none text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600"
|
|
184
|
+
class="flex h-7 w-7 flex-none cursor-pointer items-center justify-center rounded-lg text-[17px] leading-none text-neutral-400 hover:bg-neutral-100 hover:text-neutral-600" aria-label="Attach file"><span data-icon="Plus" class="h-3.5 w-3.5"></span></button>
|
|
213
185
|
<input id="attach-input" type="file" multiple class="hidden" />
|
|
214
186
|
<textarea id="input" rows="1"
|
|
215
187
|
class="block max-h-48 min-w-0 flex-1 resize-none bg-transparent px-1 py-0.5 focus:outline-none"
|
|
216
188
|
placeholder="Message…"></textarea>
|
|
217
|
-
<button type="button" id="stop" title="Stop the running turn"
|
|
189
|
+
<button type="button" id="stop" title="Stop the running turn" aria-label="Stop the running turn"
|
|
218
190
|
class="hidden h-7 w-7 flex-none cursor-pointer items-center justify-center rounded-lg bg-red-50 text-red-600 hover:bg-red-100">
|
|
219
|
-
<
|
|
220
|
-
<rect x="3.5" y="3.5" width="9" height="9" rx="1.5" />
|
|
221
|
-
</svg>
|
|
191
|
+
<span data-icon="Square" class="h-3.5 w-3.5"></span>
|
|
222
192
|
</button>
|
|
223
|
-
<!-- Style + icon double as the state display: indigo
|
|
193
|
+
<!-- Style + icon double as the state display: indigo arrow = send, amber clock = queue -->
|
|
224
194
|
<button type="submit" id="send" title="Send">
|
|
225
|
-
<
|
|
226
|
-
|
|
227
|
-
<path d="M14.5 1.5 7 9m7.5-7.5-4.2 12.6L7 9 1.7 6.7l12.8-5.2z" />
|
|
228
|
-
</svg>
|
|
229
|
-
<svg id="send-queue" viewBox="0 0 16 16" fill="none" stroke="currentColor"
|
|
230
|
-
stroke-width="1.5" stroke-linecap="round" class="hidden h-3.5 w-3.5">
|
|
231
|
-
<circle cx="8" cy="8" r="6" />
|
|
232
|
-
<path d="M8 4.75V8l2.4 1.5" />
|
|
233
|
-
</svg>
|
|
195
|
+
<span id="send-arrow" data-icon="ArrowUp" class="h-3.5 w-3.5"></span>
|
|
196
|
+
<span id="send-queue" data-icon="Clock" class="hidden h-3.5 w-3.5"></span>
|
|
234
197
|
</button>
|
|
235
198
|
</div>
|
|
236
199
|
</div>
|
|
237
200
|
</form>
|
|
238
201
|
</main>
|
|
239
202
|
|
|
240
|
-
<dialog id="new-dialog" class="m-auto w-[min(24rem,92vw)] rounded-3xl border border-neutral-200 p-5 shadow-xl backdrop:bg-black/20">
|
|
241
|
-
<form id="new-form" method="dialog" class="flex flex-col gap-3">
|
|
242
|
-
<h3 class="font-semibold">New session</h3>
|
|
243
|
-
<label class="flex flex-col gap-1 text-[13px] text-neutral-600">
|
|
244
|
-
Working directory
|
|
245
|
-
<input id="new-cwd" type="text" required placeholder="/path/to/project"
|
|
246
|
-
class="w-full rounded-md border border-neutral-300 px-2 py-1.5 font-mono text-[13px] focus:border-indigo-400 focus:outline-none" />
|
|
247
|
-
</label>
|
|
248
|
-
<div class="flex justify-end gap-2">
|
|
249
|
-
<button type="button" id="new-cancel" class="btn text-[13px]">Cancel</button>
|
|
250
|
-
<button type="submit" class="btn btn-primary text-[13px]">Create</button>
|
|
251
|
-
</div>
|
|
252
|
-
</form>
|
|
253
|
-
</dialog>
|
|
254
|
-
|
|
255
203
|
<!-- Not m-auto: a palette that grows downward as you type should not also
|
|
256
204
|
drift upward to stay centred. Pinned near the top instead, which is
|
|
257
|
-
where the eye already is and where every other ⌘K lives.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
205
|
+
where the eye already is and where every other ⌘K lives. A solid
|
|
206
|
+
surface (docs/design/06-ui-ux.md): glass is for chrome, and this is
|
|
207
|
+
something you read. The edge and shadow tokens are set in style.css;
|
|
208
|
+
a click on the backdrop lands on the dialog element itself and closes
|
|
209
|
+
it (palette.ts). -->
|
|
210
|
+
<dialog id="palette" class="mx-auto mb-auto mt-[12vh] w-[36rem] max-w-[92vw] rounded-3xl border p-0 backdrop:bg-black/25">
|
|
211
|
+
<div class="flex h-[3.25rem] items-center gap-3 border-b border-neutral-200/70 px-4">
|
|
212
|
+
<span data-icon="Search" aria-hidden="true" class="h-[1.125rem] w-[1.125rem] flex-none text-neutral-400"></span>
|
|
213
|
+
<input id="palette-input" type="text" placeholder="Search sessions, messages and Console…" autocomplete="off" spellcheck="false"
|
|
214
|
+
class="min-w-0 flex-1 bg-transparent text-[1.0625rem] leading-6 placeholder:text-neutral-400 focus:outline-none" />
|
|
215
|
+
<kbd class="flex-none rounded-md border border-neutral-200 px-1.5 font-sans text-[0.6875rem] leading-5 text-neutral-500">esc</kbd>
|
|
216
|
+
</div>
|
|
217
|
+
<ul id="palette-list" role="listbox" aria-label="Results" class="max-h-[60vh] overflow-y-auto px-2 pb-2 text-[0.9375rem]"></ul>
|
|
218
|
+
<div class="flex items-center justify-between border-t border-neutral-200/70 px-4 py-1.5 text-[0.75rem] leading-4 text-neutral-500">
|
|
219
|
+
<span id="palette-keys">↑↓ navigate · ↵ open</span>
|
|
220
|
+
<span id="palette-count"></span>
|
|
264
221
|
</div>
|
|
265
|
-
<ul id="archive-list" class="max-h-[60vh] overflow-y-auto py-1 text-[13.5px]"></ul>
|
|
266
222
|
</dialog>
|
|
267
223
|
|
|
268
|
-
<!-- Full-size view of a thumbnail; a
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
image
|
|
224
|
+
<!-- Full-size view of a thumbnail; a click on the image zooms about the
|
|
225
|
+
point and a second one fits it again, dragging pans what is magnified, a
|
|
226
|
+
click beside it — or the ✕, or Esc — closes. The arrows page through the
|
|
227
|
+
gallery it was opened from, as do ← / →; they hide when there is only one
|
|
228
|
+
image to look at. The dialog fills the viewport rather than hugging the
|
|
229
|
+
image, so the controls sit at the screen's edges and a tall shot and a
|
|
230
|
+
wide one don't move the one under your thumb; #image-stage is the box a
|
|
231
|
+
zoomed image scrolls inside (ui/attachments.ts). -->
|
|
275
232
|
<!-- The size is written out, not left to `inset-0`: a dialog is `width:
|
|
276
233
|
fit-content` in the UA sheet, and an inset pair does not stretch a box
|
|
277
234
|
that already has a width — it sized itself to the image and sat in the
|
|
@@ -279,12 +236,25 @@
|
|
|
279
236
|
of on #image-stage. -->
|
|
280
237
|
<dialog id="image-dialog" class="fixed inset-0 m-0 h-[100dvh] w-full max-h-none max-w-none bg-transparent p-0 backdrop:bg-black/70">
|
|
281
238
|
<div id="image-stage" class="flex h-full w-full items-center justify-center overflow-hidden">
|
|
282
|
-
|
|
239
|
+
<!-- The width leaves the arrows their gutters wherever there is room for
|
|
240
|
+
them: a wide shot at 92vw ran under both, which is what "the buttons
|
|
241
|
+
are gone" was. Below md there is no such room — taking 9rem off a
|
|
242
|
+
390px screen would shrink every portrait screenshot to fit controls
|
|
243
|
+
that are only sometimes there — so the arrows overlay the image and
|
|
244
|
+
the rim in style.css is what keeps them legible over it.
|
|
245
|
+
draggable=false: the browser's own image drag would race the pan. -->
|
|
246
|
+
<img id="image-full" alt="" draggable="false"
|
|
247
|
+
class="max-h-[92dvh] max-w-[92vw] cursor-zoom-in rounded-xl object-contain md:max-w-[calc(100vw-9rem)]" />
|
|
283
248
|
</div>
|
|
284
249
|
<!-- Siblings of the stage, not children of it: the stage is what scrolls
|
|
285
|
-
when zoomed, and
|
|
286
|
-
|
|
287
|
-
|
|
250
|
+
when zoomed, and a control inside it would scroll away with the image.
|
|
251
|
+
.lightbox-btn is the round scrim button; where each one sits is a
|
|
252
|
+
utility beside it, so no two of them set the same property. -->
|
|
253
|
+
<button type="button" id="image-prev" aria-label="Previous image" class="lightbox-btn left-2 top-1/2 -translate-y-1/2"><span data-icon="ChevronLeft" class="h-6 w-6"></span></button>
|
|
254
|
+
<button type="button" id="image-next" aria-label="Next image" class="lightbox-btn right-2 top-1/2 -translate-y-1/2"><span data-icon="ChevronRight" class="h-6 w-6"></span></button>
|
|
255
|
+
<!-- The way out on a touch screen: tapping the image now zooms it, and the
|
|
256
|
+
scrim beside a fitted shot is a 4vw strip — not a thumb's target. -->
|
|
257
|
+
<button type="button" id="image-close" aria-label="Close" class="lightbox-btn right-2 top-2"><span data-icon="X" class="h-6 w-6"></span></button>
|
|
288
258
|
</dialog>
|
|
289
259
|
|
|
290
260
|
<!-- Text preview of an agent attachment — the Files view's code pane fills
|
|
Binary file
|
|
Binary file
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"start_url": "/",
|
|
9
9
|
"scope": "/",
|
|
10
10
|
"display": "standalone",
|
|
11
|
-
"background_color": "#
|
|
12
|
-
"theme_color": "#
|
|
11
|
+
"background_color": "#f1f4f3",
|
|
12
|
+
"theme_color": "#f1f4f3",
|
|
13
13
|
"categories": ["developer", "productivity", "utilities"],
|
|
14
14
|
"launch_handler": { "client_mode": "focus-existing" },
|
|
15
15
|
"icons": [
|
|
Binary file
|
|
Binary file
|
package/dist/web/public/sw.js
CHANGED
|
@@ -18,6 +18,18 @@ button{margin-top:1rem;padding:.5rem 1rem;border:1px solid light-dark(#d4d4d4,#3
|
|
|
18
18
|
<p class="dim">This device is offline, or the server is not answering.</p>
|
|
19
19
|
<button onclick="location.reload()">Try again</button></main></body></html>`;
|
|
20
20
|
|
|
21
|
+
/** A payload URL is data: resolved against this origin, and replaced by the
|
|
22
|
+
* root if it lands anywhere else — a notification may not open a foreign page. */
|
|
23
|
+
const here = (url) => {
|
|
24
|
+
const root = new URL("/", self.location.origin);
|
|
25
|
+
try {
|
|
26
|
+
const target = new URL(url || "/", self.location.origin);
|
|
27
|
+
return target.origin === root.origin ? target : root;
|
|
28
|
+
} catch {
|
|
29
|
+
return root;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
21
33
|
self.addEventListener("install", () => self.skipWaiting());
|
|
22
34
|
|
|
23
35
|
self.addEventListener("activate", (event) => {
|
|
@@ -66,7 +78,7 @@ self.addEventListener("push", (event) => {
|
|
|
66
78
|
icon: "/icon-192.png",
|
|
67
79
|
badge: "/icon-32.png",
|
|
68
80
|
timestamp: Date.now(),
|
|
69
|
-
data: { url: data.url
|
|
81
|
+
data: { url: here(data.url).href },
|
|
70
82
|
});
|
|
71
83
|
// The home-screen badge is the only trace left once a notification is
|
|
72
84
|
// dismissed; the page recomputes it from the session list when it opens.
|
|
@@ -76,7 +88,7 @@ self.addEventListener("push", (event) => {
|
|
|
76
88
|
|
|
77
89
|
self.addEventListener("notificationclick", (event) => {
|
|
78
90
|
event.notification.close();
|
|
79
|
-
const target =
|
|
91
|
+
const target = here(event.notification.data?.url);
|
|
80
92
|
event.waitUntil((async () => {
|
|
81
93
|
const clients = await self.clients.matchAll({ type: "window", includeUncontrolled: true });
|
|
82
94
|
// An open workbench is focused and pointed at the session, rather than
|
package/dist/web/public/sw.js.br
CHANGED
|
Binary file
|
package/dist/web/public/sw.js.gz
CHANGED
|
Binary file
|