lampson 0.2.7 → 0.2.9
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/.env.example +10 -1
- package/README.md +9 -3
- package/bin/lampson.js +1 -1
- package/chat.syn +112 -8
- package/cli.syn +143 -7
- package/edge.syn +26 -0
- package/hub.tpl.syn +127 -6
- package/lampson.ps1 +43 -2
- package/lampson.sh +40 -2
- package/lib/agents.syn +30 -9
- package/lib/approvals.syn +2 -2
- package/lib/auth.syn +274 -0
- package/lib/computer.syn +2000 -0
- package/lib/computer_judge.syn +410 -0
- package/lib/fs.syn +242 -0
- package/lib/git.syn +2 -2
- package/lib/judge.syn +78 -0
- package/lib/line.syn +2 -2
- package/lib/loop.syn +41 -8
- package/lib/lsp.syn +4 -4
- package/lib/mcp.syn +20 -4
- package/lib/md.syn +11 -11
- package/lib/origin.syn +67 -0
- package/lib/permission.syn +47 -2
- package/lib/prompt.syn +10 -1
- package/lib/provider.syn +70 -20
- package/lib/schedule.syn +12 -12
- package/lib/session.syn +5 -5
- package/lib/settings.syn +65 -1
- package/lib/skills.syn +22 -6
- package/lib/tools/bash.syn +1 -1
- package/lib/tools/common.syn +1 -1
- package/lib/tools/fetch.syn +600 -0
- package/lib/tools/grep.syn +1 -1
- package/lib/tools/memo.syn +3 -3
- package/lib/tools/proc.syn +38 -20
- package/lib/tools/qr.js +26 -0
- package/lib/tools/url.syn +220 -0
- package/lib/tools.syn +25 -2
- package/lib/trace.syn +2 -2
- package/lib/tree.syn +29 -13
- package/lib/update.syn +1 -1
- package/lib/workspaces.syn +202 -36
- package/package.json +12 -3
- package/public/apple-touch-icon.png +0 -0
- package/public/badge-96.png +0 -0
- package/public/css/code.css +48 -0
- package/public/css/hub.css +9 -0
- package/public/css/login.css +16 -0
- package/public/css/panel.css +30 -0
- package/public/css/sidebar.css +21 -0
- package/public/css/tokens.css +1 -1
- package/public/hub.html +11 -1
- package/public/icon-192.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/icon-maskable-512.png +0 -0
- package/public/icons-src/badge.svg +12 -0
- package/public/icons-src/icon-maskable.svg +15 -0
- package/public/icons-src/icon.svg +13 -0
- package/public/index.html +14 -3
- package/public/js/agents.js +1 -1
- package/public/js/chat.js +1 -1
- package/public/js/config.js +145 -2
- package/public/js/core.js +5 -3
- package/public/js/devices.js +80 -0
- package/public/js/editor.js +232 -0
- package/public/js/login.js +78 -0
- package/public/js/procs.js +1 -1
- package/public/js/pwa.js +5 -0
- package/public/js/tree.js +224 -14
- package/public/login.html +43 -0
- package/public/manifest.webmanifest +16 -0
- package/public/offline.html +24 -0
- package/public/sw.js +63 -0
- package/public/vendor/highlight.min.js +1343 -0
- package/public/vendor/qrcode.js +2297 -0
- package/skills/computer-use/SKILL.md +178 -0
- package/skills/lampson/SKILL.md +13 -0
- package/web.syn +82 -7
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
6
|
+
<meta name="theme-color" content="#131412">
|
|
7
|
+
<meta name="mobile-web-app-capable" content="yes">
|
|
8
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
9
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
10
|
+
<link rel="manifest" href="/manifest.webmanifest">
|
|
11
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
12
|
+
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
|
13
|
+
<title>Lampson · entrar</title>
|
|
14
|
+
<link rel="stylesheet" href="/css/tokens.css">
|
|
15
|
+
<link rel="stylesheet" href="/css/login.css">
|
|
16
|
+
<script>(function(){try{var t=localStorage.getItem('lampson.theme');if(t!=='light'&&t!=='dark'){t='dark';}document.documentElement.setAttribute('data-theme',t);}catch(e){}})();</script>
|
|
17
|
+
</head>
|
|
18
|
+
<body class="auth">
|
|
19
|
+
<main class="authbox">
|
|
20
|
+
<img src="/favicon.svg" alt="" class="logo" width="48" height="48">
|
|
21
|
+
<!-- login: dispositivo ya emparejado -->
|
|
22
|
+
<section id="login" hidden>
|
|
23
|
+
<p class="eyebrow">lampson</p>
|
|
24
|
+
<h1>Entrar</h1>
|
|
25
|
+
<p class="lead">Usá la passkey de este dispositivo: huella, cara o el bloqueo de pantalla.</p>
|
|
26
|
+
<button class="primary" id="doLogin">Entrar con passkey</button>
|
|
27
|
+
<p class="hint">¿Dispositivo nuevo? En la PC donde corre lampson abrí <b>dispositivos</b> → <b>emparejar</b> y escaneá el QR.</p>
|
|
28
|
+
</section>
|
|
29
|
+
<!-- emparejar: llegó desde el QR (/pair#<código>) -->
|
|
30
|
+
<section id="pair" hidden>
|
|
31
|
+
<p class="eyebrow">emparejar dispositivo</p>
|
|
32
|
+
<h1>Conectar con tu PC</h1>
|
|
33
|
+
<p class="lead">Vas a crear una passkey para este dispositivo. Después entrás solo con la huella o la cara, sin contraseñas.</p>
|
|
34
|
+
<label class="field">nombre del dispositivo<input id="devName" maxlength="60" autocomplete="off" spellcheck="false"></label>
|
|
35
|
+
<button class="primary" id="doPair">Crear passkey</button>
|
|
36
|
+
<p class="hint">El código del QR vale 5 minutos y sirve una sola vez.</p>
|
|
37
|
+
</section>
|
|
38
|
+
<p class="msg" id="msg" role="status"></p>
|
|
39
|
+
</main>
|
|
40
|
+
<script src="/js/pwa.js"></script>
|
|
41
|
+
<script src="/js/login.js"></script>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "/",
|
|
3
|
+
"name": "Lampson",
|
|
4
|
+
"short_name": "Lampson",
|
|
5
|
+
"description": "Tu agente de código: workspaces, sesiones y tareas desde el celular.",
|
|
6
|
+
"start_url": "/",
|
|
7
|
+
"scope": "/",
|
|
8
|
+
"display": "standalone",
|
|
9
|
+
"background_color": "#131412",
|
|
10
|
+
"theme_color": "#131412",
|
|
11
|
+
"icons": [
|
|
12
|
+
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" },
|
|
13
|
+
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" },
|
|
14
|
+
{ "src": "/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
6
|
+
<meta name="theme-color" content="#131412">
|
|
7
|
+
<title>Lampson · sin conexión</title>
|
|
8
|
+
<link rel="stylesheet" href="/css/tokens.css">
|
|
9
|
+
<style>
|
|
10
|
+
body { display:flex; align-items:center; justify-content:center; min-height:100vh; padding:24px; }
|
|
11
|
+
.box { max-width:420px; }
|
|
12
|
+
h1 { font:600 22px/1.3 var(--serif); margin:0 0 8px; }
|
|
13
|
+
p { color:var(--ink-2); margin:0 0 16px; }
|
|
14
|
+
button { font:400 13px var(--mono); padding:8px 14px; background:transparent; color:var(--accent); border:1px solid var(--accent); border-radius:var(--r); }
|
|
15
|
+
</style>
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<div class="box">
|
|
19
|
+
<h1>Tu PC no responde</h1>
|
|
20
|
+
<p>Lampson corre en tu PC: tiene que estar prendida, con lampson y el túnel andando (<code>lampson --install</code> lo arranca solo al iniciar sesión). Si estás sin señal, revisá tu conexión.</p>
|
|
21
|
+
<button onclick="location.reload()">reintentar</button>
|
|
22
|
+
</div>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
package/public/sw.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// sw.js — service worker de la PWA de lampson (base: el scaffold de `synsema init --pwa`).
|
|
2
|
+
// Red primero para todo: lampson cambia seguido y es una herramienta en vivo; mostrar una versión vieja de la UI
|
|
3
|
+
// sería peor que avisar. El caché solo sirve para abrir sin red: íconos, CSS/JS/fuentes y una página «sin conexión».
|
|
4
|
+
// Nunca se cachea el API (/api/…, /w/<slug>/api/…) ni una respuesta que falló, ni las páginas con datos del usuario.
|
|
5
|
+
const CACHE = "lampson-shell-v2";
|
|
6
|
+
const SHELL = ["/offline.html", "/manifest.webmanifest", "/icon-192.png", "/favicon.svg", "/css/tokens.css"];
|
|
7
|
+
|
|
8
|
+
self.addEventListener("install", (e) => {
|
|
9
|
+
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(SHELL)).then(() => self.skipWaiting()));
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
self.addEventListener("activate", (e) => {
|
|
13
|
+
e.waitUntil(
|
|
14
|
+
caches.keys()
|
|
15
|
+
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
|
|
16
|
+
.then(() => self.clients.claim())
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const tunnelDown = (res) => res.headers.get("x-synsema-tunnel") === "offline" || [502, 503, 504, 521, 522, 523, 524, 530].includes(res.status);
|
|
21
|
+
const isApi = (p) => p.startsWith("/api/") || /^\/w\/[^/]+\/(api|approve)\//.test(p);
|
|
22
|
+
const isAsset = (p) => /^\/(css|js|fonts|vendor)\//.test(p) || /\.(png|svg|webmanifest|woff2)$/.test(p);
|
|
23
|
+
|
|
24
|
+
self.addEventListener("fetch", (e) => {
|
|
25
|
+
const url = new URL(e.request.url);
|
|
26
|
+
if (e.request.method !== "GET" || url.origin !== self.location.origin) return;
|
|
27
|
+
if (isApi(url.pathname)) return; // SSE, WebSocket y JSON van directo a la red, sin tocar
|
|
28
|
+
if (e.request.mode === "navigate") {
|
|
29
|
+
// PC apagada o lampson caído: sin red → error de fetch; detrás de un túnel, el túnel SÍ responde, con su propia
|
|
30
|
+
// página de error (Cloudflare: 530/1033, 502, 504; un túnel de la plataforma marca X-Synsema-Tunnel: offline).
|
|
31
|
+
// En los dos casos, la pantalla de lampson. El hub nunca responde una página con esos códigos.
|
|
32
|
+
e.respondWith(fetch(e.request).then((res) => {
|
|
33
|
+
if (tunnelDown(res)) return caches.match("/offline.html").then((c) => c || res);
|
|
34
|
+
return res;
|
|
35
|
+
}).catch(() => caches.match("/offline.html")));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (isAsset(url.pathname)) {
|
|
39
|
+
e.respondWith(fetch(e.request).then(async (res) => {
|
|
40
|
+
if (res.ok) { const c = await caches.open(CACHE); await c.put(e.request, res.clone()); }
|
|
41
|
+
return res;
|
|
42
|
+
}).catch(async () => (await caches.match(e.request)) || Response.error()));
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// push (para después: avisos de aprobaciones y de tareas terminadas)
|
|
47
|
+
self.addEventListener("push", (e) => {
|
|
48
|
+
let data = {};
|
|
49
|
+
try { data = e.data ? e.data.json() : {}; } catch (_) { data = { body: e.data ? e.data.text() : "" }; }
|
|
50
|
+
const opts = { body: data.body || "", icon: "/icon-192.png", badge: "/badge-96.png", data };
|
|
51
|
+
if (data.tag) { opts.tag = String(data.tag); opts.renotify = true; }
|
|
52
|
+
e.waitUntil(self.registration.showNotification(data.title || "Lampson", opts));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
self.addEventListener("notificationclick", (e) => {
|
|
56
|
+
e.notification.close();
|
|
57
|
+
const url = (e.notification.data && e.notification.data.url) || "/";
|
|
58
|
+
e.waitUntil(clients.matchAll({ type: "window", includeUncontrolled: true }).then((wins) => {
|
|
59
|
+
const win = wins.find((w) => "focus" in w);
|
|
60
|
+
if (win) { win.postMessage({ type: "notificationclick", url }); return win.focus(); }
|
|
61
|
+
return clients.openWindow(url);
|
|
62
|
+
}));
|
|
63
|
+
});
|