pelican-cc 0.3.0 → 0.4.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/CHANGELOG.md +199 -0
- package/README.md +8 -6
- package/dist/server/index.js +6238 -1001
- package/dist/server/index.js.map +4 -4
- package/dist/web/assets/Chat-hw_dVyZ5.js +101 -0
- package/dist/web/assets/Chat-hw_dVyZ5.js.br +0 -0
- package/dist/web/assets/Chat-hw_dVyZ5.js.gz +0 -0
- package/dist/web/assets/ModelSheet-DDh0NARP.js +1 -0
- package/dist/web/assets/ModelSheet-DDh0NARP.js.br +0 -0
- package/dist/web/assets/ModelSheet-DDh0NARP.js.gz +0 -0
- package/dist/web/assets/Settings-ByxVBoK1.js +4 -0
- package/dist/web/assets/Settings-ByxVBoK1.js.br +0 -0
- package/dist/web/assets/Settings-ByxVBoK1.js.gz +0 -0
- package/dist/web/assets/Usage-DvP3bGmY.js +1 -0
- package/dist/web/assets/Usage-DvP3bGmY.js.br +0 -0
- package/dist/web/assets/Usage-DvP3bGmY.js.gz +0 -0
- package/dist/web/assets/WorkspaceChanges-Cnv5Vi7J.js +1 -0
- package/dist/web/assets/WorkspaceChanges-Cnv5Vi7J.js.br +0 -0
- package/dist/web/assets/WorkspaceChanges-Cnv5Vi7J.js.gz +0 -0
- package/dist/web/assets/WorkspaceFiles-CSlYqC41.js +1 -0
- package/dist/web/assets/WorkspaceFiles-CSlYqC41.js.br +0 -0
- package/dist/web/assets/WorkspaceFiles-CSlYqC41.js.gz +0 -0
- package/dist/web/assets/index-Ck4Wpk8v.css +2 -0
- package/dist/web/assets/index-Ck4Wpk8v.css.br +0 -0
- package/dist/web/assets/index-Ck4Wpk8v.css.gz +0 -0
- package/dist/web/assets/index-fRwaTlu9.js +40 -0
- package/dist/web/assets/index-fRwaTlu9.js.br +0 -0
- package/dist/web/assets/index-fRwaTlu9.js.gz +0 -0
- package/dist/web/assets/usage-CHTS1DtT.js +1 -0
- package/dist/web/assets/usage-CHTS1DtT.js.br +0 -0
- package/dist/web/assets/usage-CHTS1DtT.js.gz +0 -0
- package/dist/web/index.html +2 -2
- package/dist/web/index.html.br +0 -0
- package/dist/web/index.html.gz +0 -0
- package/dist/web/sw.js +56 -14
- package/dist/web/sw.js.br +0 -0
- package/dist/web/sw.js.gz +0 -0
- package/npm-shrinkwrap.json +114 -598
- package/package.json +3 -3
- package/dist/web/assets/Chat-BZ4Kv_y0.js +0 -73
- package/dist/web/assets/Chat-BZ4Kv_y0.js.br +0 -0
- package/dist/web/assets/Chat-BZ4Kv_y0.js.gz +0 -0
- package/dist/web/assets/ModelSheet-CrgB7jGC.js +0 -1
- package/dist/web/assets/ModelSheet-CrgB7jGC.js.br +0 -0
- package/dist/web/assets/ModelSheet-CrgB7jGC.js.gz +0 -0
- package/dist/web/assets/Settings-BYSfCOfJ.js +0 -3
- package/dist/web/assets/Settings-BYSfCOfJ.js.br +0 -0
- package/dist/web/assets/Settings-BYSfCOfJ.js.gz +0 -0
- package/dist/web/assets/index-DTXoHe9U.js +0 -30
- package/dist/web/assets/index-DTXoHe9U.js.br +0 -0
- package/dist/web/assets/index-DTXoHe9U.js.gz +0 -0
- package/dist/web/assets/index-DYo6H59g.css +0 -2
- package/dist/web/assets/index-DYo6H59g.css.br +0 -0
- package/dist/web/assets/index-DYo6H59g.css.gz +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{C as e}from"./index-fRwaTlu9.js";var t=e=>e.input+e.output+e.cacheRead+e.cacheWrite;function n(e){let t=e.input+e.cacheWrite+e.cacheRead;return t>0?e.cacheRead/t:void 0}function r(e){let t=e.replace(/^.*?(?=claude-)/,``).replace(/^claude-/,``).replace(/\[.*?\]/g,``).replace(/[@:].*$/,``).replace(/-v\d+$/,``).split(`-`).filter(e=>!/^\d{8}$/.test(e)),n=t.find(e=>/^[a-z]+$/.test(e));if(!n||!e.includes(`claude`))return e;let r=t.filter(e=>/^\d{1,2}$/.test(e));return`${n[0].toUpperCase()}${n.slice(1)}${r.length>0?` ${r.join(`.`)}`:``}`}function i(e){return e.signedIn===!0&&!e.plan}var a=`estimated at API prices`;function o(e,t=0){return`${e>=100?`$${Math.round(e).toLocaleString(`en`)}`:`$${e.toFixed(2)}`}, ${a}${t>0?`; ${t} ${t===1?`session has`:`sessions have`} no estimate`:``}`}function s(e){let t=Math.max(0,Math.round(e));if(t<1e4)return t.toLocaleString(`en`);let n=[[0xe8d4a51000,`T`],[1e9,`B`],[1e6,`M`],[1e3,`K`]];for(let e=0;e<n.length;e+=1){let[r,i]=n[e];if(t<r)continue;let a=t/r,o=a>=100?Math.round(a):Math.round(a*10)/10;return o>=1e3&&e>0?`${Math.round(t/n[e-1][0]*10)/10}${n[e-1][1]}`:`${o}${i}`}return String(t)}var c=e=>e>0&&e<.005?`<1%`:`${Math.round(e*100)}%`;function l(e){if(e<6e4)return`${Math.max(1,Math.round(e/1e3))}s`;let t=Math.round(e/6e4);if(t<60)return`${t}m`;let n=Math.floor(t/60);if(n<24)return t%60?`${n}h ${t%60}m`:`${n}h`;let r=Math.floor(n/24);return n%24?`${r}d ${n%24}h`:`${r}d`}var u=e=>new Date(`${e}T00:00:00Z`),d=e=>u(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`,timeZone:`UTC`}),f=e=>u(e).toLocaleDateString(void 0,{weekday:`short`,timeZone:`UTC`}),p=e=>u(e).toLocaleDateString(void 0,{weekday:`short`,month:`short`,day:`numeric`,timeZone:`UTC`});function m(e,t){return e===`7d`?`in the last 7 days`:e===`30d`?`in the last 30 days`:`since ${d(t.tokensSince??t.from)}`}var h=e=>new Date(2e3,0,1,e).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`});function g(e){if(e.length<2)return;let t;for(let n of[...new Set(e)].sort((e,t)=>e-t)){let r=e.filter(e=>(e-n+24)%24<4).length;r*3>=e.length*2&&(!t||r>t[1])&&(t=[n,r])}return t&&[t[0],(t[0]+4)%24]}var _=e=>e===1?`once`:e===2?`twice`:`${e} times`,v=t=>`“${e(t,40)}”`;function y(e,r=e=>new Date(e).getHours()){let i=[],a=t(e.tokens);if(a>0){let t=e.projects[0];e.projects.length>1&&t&&t.tokens/a>=.4&&i.push(`${c(t.tokens/a)} of the tokens went to ${t.name}.`);let r=e.sessions[0];e.sessions.length>1&&r&&r.tokens/a>=.25&&i.push(`One session, ${v(r.title)}, took ${c(r.tokens/a)}.`);let o=n(e.tokens);o!==void 0&&i.push(o>=.6?`${c(o)} of the input was read from the cache.`:`Only ${c(o)} of the input was read from the cache. After a pause longer than the cache lasts, the next message sends the whole conversation again.`)}let o=e.limits.filter(e=>e.kind===`session`);if(o.length===1)i.push(`The 5-hour limit was reached once, around ${h(r(o[0].at))}.`);else if(o.length>1){let e=g(o.map(e=>r(e.at)));i.push(`The 5-hour limit was reached ${_(o.length)}${e?`, mostly between ${h(e[0])} and ${h(e[1])}`:``}.`)}let s=e.limits.filter(e=>e.kind===`weekly`);if(s.length>0){let e=s.length===1?`, on ${new Date(s[0].at).toLocaleDateString(void 0,{weekday:`short`,month:`short`,day:`numeric`})}`:``;i.push(`The weekly limit was reached ${_(s.length)}${e}.`)}let u=e.limits.filter(e=>e.kind===`model`);u.length>0&&i.push(`A model’s weekly limit was reached ${_(u.length)}.`),e.waits&&e.waits.ms>=6e4&&i.push(`In Pelican, Claude waited ${l(e.waits.ms)} for your answers${e.waits.count>=3?`, ${l(e.waits.longest)} at most`:``}.`);let[d,...f]=e.compacted;return d&&i.push(f.length===0?`${v(d.title)} was compacted ${_(d.times)}. A new session for each new task keeps the context small.`:`${e.compacted.length} sessions were compacted three times or more, ${v(d.title)} ${_(d.times)}. A new session for each new task keeps the context small.`),i}export{c as a,_ as c,i as d,o as f,p as i,f as l,t as m,d as n,m as o,r as p,y as r,l as s,s as t,n as u};
|
|
Binary file
|
|
Binary file
|
package/dist/web/index.html
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<link rel="manifest" href="./manifest.webmanifest" />
|
|
15
15
|
<title>Pelican</title>
|
|
16
|
-
<script type="module" crossorigin src="./assets/index-
|
|
17
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
16
|
+
<script type="module" crossorigin src="./assets/index-fRwaTlu9.js"></script>
|
|
17
|
+
<link rel="stylesheet" crossorigin href="./assets/index-Ck4Wpk8v.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
package/dist/web/index.html.br
CHANGED
|
Binary file
|
package/dist/web/index.html.gz
CHANGED
|
Binary file
|
package/dist/web/sw.js
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
self.addEventListener('install', () => self.skipWaiting());
|
|
4
4
|
self.addEventListener('activate', (event) => event.waitUntil(self.clients.claim()));
|
|
5
5
|
|
|
6
|
+
/** Allow and Deny, where the device shows buttons on a notification. */
|
|
7
|
+
const canAnswer = () => typeof Notification !== 'undefined' && (Notification.maxActions ?? 0) >= 2;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Android's pop-up shows a notification's title and one line of its text beside the buttons, the
|
|
11
|
+
* rest only once it is expanded: there a command gets them only when it fits that line.
|
|
12
|
+
*/
|
|
13
|
+
const onAndroid = () => /Android/.test(self.navigator?.userAgent ?? '') || self.navigator?.userAgentData?.platform === 'Android';
|
|
14
|
+
|
|
6
15
|
self.addEventListener('push', (event) => {
|
|
7
16
|
let data = {};
|
|
8
17
|
try {
|
|
@@ -10,6 +19,9 @@ self.addEventListener('push', (event) => {
|
|
|
10
19
|
} catch {
|
|
11
20
|
data = { title: 'Claude Code', body: event.data ? event.data.text() : '' };
|
|
12
21
|
}
|
|
22
|
+
// A request Claude waits on can be answered from here: yes or no to a tool it wants to use.
|
|
23
|
+
const answer = typeof data.request === 'string' && typeof data.sessionId === 'string' && canAnswer()
|
|
24
|
+
&& (data.fitsOneLine === true || !onAndroid());
|
|
13
25
|
event.waitUntil(
|
|
14
26
|
self.registration.showNotification(data.title || 'Claude Code', {
|
|
15
27
|
body: data.body || '',
|
|
@@ -17,24 +29,54 @@ self.addEventListener('push', (event) => {
|
|
|
17
29
|
renotify: Boolean(data.tag),
|
|
18
30
|
icon: 'icon-192.png',
|
|
19
31
|
badge: 'badge-96.png',
|
|
20
|
-
data: { url: data.url, sessionId: data.sessionId },
|
|
32
|
+
data: { url: data.url, sessionId: data.sessionId, ...(answer ? { request: data.request } : {}) },
|
|
33
|
+
...(answer ? { actions: [{ action: 'allow', title: 'Allow' }, { action: 'deny', title: 'Deny' }] } : {}),
|
|
21
34
|
}),
|
|
22
35
|
);
|
|
23
36
|
});
|
|
24
37
|
|
|
38
|
+
/** Shows the session: in an open page, or in a new one. */
|
|
39
|
+
async function open(url, sessionId) {
|
|
40
|
+
const windows = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
|
|
41
|
+
// An open page shows the session itself, even when another page frames it.
|
|
42
|
+
for (const client of windows) {
|
|
43
|
+
if (sessionId) client.postMessage({ type: 'open-session', sessionId });
|
|
44
|
+
if ('focus' in client) {
|
|
45
|
+
await client.focus();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (url) await self.clients.openWindow(url);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Answers the request through the same route as the page, the same way: marked as Pelican's, from
|
|
54
|
+
* Pelican's own origin, with the sign-in this browser has. A request answered already, here or
|
|
55
|
+
* anywhere, is no longer pending, and the answer changes nothing (409). Whether it was taken, or
|
|
56
|
+
* the request is gone; false when it could not be sent (signed out, out of reach).
|
|
57
|
+
*/
|
|
58
|
+
async function decide(sessionId, request, behavior) {
|
|
59
|
+
const url = new URL(`api/sessions/${encodeURIComponent(sessionId)}/permissions/${encodeURIComponent(request)}`, self.registration.scope);
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
credentials: 'same-origin',
|
|
64
|
+
headers: { 'X-Pelican': '1', 'Content-Type': 'application/json' },
|
|
65
|
+
body: JSON.stringify({ behavior }),
|
|
66
|
+
});
|
|
67
|
+
return response.ok || response.status === 409;
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
25
73
|
self.addEventListener('notificationclick', (event) => {
|
|
26
74
|
event.notification.close();
|
|
27
|
-
const { url, sessionId } = event.notification.data || {};
|
|
28
|
-
event.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
await client.focus();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (url) await self.clients.openWindow(url);
|
|
39
|
-
})());
|
|
75
|
+
const { url, sessionId, request } = event.notification.data || {};
|
|
76
|
+
if ((event.action === 'allow' || event.action === 'deny') && sessionId && request) {
|
|
77
|
+
// Answered from the lock screen; when that cannot be done, the session opens to answer it there.
|
|
78
|
+
event.waitUntil(decide(sessionId, request, event.action).then((done) => (done ? undefined : open(url, sessionId))));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
event.waitUntil(open(url, sessionId));
|
|
40
82
|
});
|
package/dist/web/sw.js.br
CHANGED
|
Binary file
|
package/dist/web/sw.js.gz
CHANGED
|
Binary file
|