@lifeaitools/clauth 1.19.2 → 1.19.4

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.
Files changed (2) hide show
  1. package/cli/commands/serve.js +107 -97
  2. package/package.json +1 -1
@@ -747,9 +747,9 @@ function dashboardHtml(port, whitelist, isStaged = false, initWriteToken = null)
747
747
  .btn-ccandme{background:linear-gradient(135deg,#1a1a2e,#16213e);color:#a78bfa;border:1px solid #4c1d95;padding:7px 16px;font-size:.85rem;border-radius:7px;cursor:pointer;font-weight:600;transition:all .15s;white-space:nowrap}
748
748
  .btn-ccandme:hover{background:linear-gradient(135deg,#2d1b69,#1e1b4b);border-color:#7c3aed;color:#c4b5fd;transform:translateY(-1px)}
749
749
  .btn-ccandme:disabled{opacity:.5;cursor:not-allowed;transform:none}
750
- .btn-monkey{background:linear-gradient(135deg,#103c2f,#0f2f3f);color:#86efac;border:1px solid #166534;padding:7px 16px;font-size:.85rem;border-radius:7px;cursor:pointer;font-weight:700;transition:all .15s;white-space:nowrap}
751
- .btn-monkey:hover{background:linear-gradient(135deg,#14532d,#155e75);border-color:#22c55e;color:#bbf7d0;transform:translateY(-1px)}
752
- .btn-monkey:disabled{opacity:.5;cursor:not-allowed;transform:none}
750
+ .btn-tintin{background:linear-gradient(135deg,#103c2f,#0f2f3f);color:#86efac;border:1px solid #166534;padding:7px 16px;font-size:.85rem;border-radius:7px;cursor:pointer;font-weight:700;transition:all .15s;white-space:nowrap}
751
+ .btn-tintin:hover{background:linear-gradient(135deg,#14532d,#155e75);border-color:#22c55e;color:#bbf7d0;transform:translateY(-1px)}
752
+ .btn-tintin:disabled{opacity:.5;cursor:not-allowed;transform:none}
753
753
  .btn-claude{background:linear-gradient(135deg,#d97706,#f59e0b);color:#0a0f1a;padding:8px 18px;font-size:.85rem;border-radius:7px;border:none;cursor:pointer;font-weight:700;letter-spacing:.3px;transition:all .15s;white-space:nowrap}
754
754
  .btn-claude:hover{filter:brightness(1.1);transform:translateY(-1px)}
755
755
  .btn-claude:disabled{opacity:.4;cursor:not-allowed;transform:none;filter:none}
@@ -766,22 +766,25 @@ function dashboardHtml(port, whitelist, isStaged = false, initWriteToken = null)
766
766
  .build-label{font-size:.85rem;color:#94a3b8;flex:1}
767
767
  .build-label strong{color:#e2e8f0}
768
768
  .build-meta{font-family:'Courier New',monospace;font-size:.75rem;color:#64748b}
769
- .monkey-panel{display:none;position:fixed;top:0;right:0;bottom:0;z-index:80;width:min(420px,calc(100vw - 24px));background:#081c1a;border-left:1px solid #14532d;padding:1rem 1.25rem;box-shadow:-22px 0 60px rgba(0,0,0,.42);overflow:auto}
770
- .monkey-panel.open{display:block}
771
- .monkey-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:.8rem}
772
- .monkey-title{font-size:.95rem;font-weight:700;color:#dcfce7}
773
- .monkey-sub{font-size:.78rem;color:#6ee7b7;margin-top:2px}
774
- .monkey-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px}
775
- .monkey-field{display:flex;flex-direction:column;gap:4px}
776
- .monkey-field label{font-size:.72rem;color:#94a3b8;text-transform:uppercase;letter-spacing:.04em;font-weight:700}
777
- .monkey-input,.monkey-textarea{background:#031312;border:1px solid #14532d;border-radius:6px;color:#e2e8f0;font-family:'Courier New',monospace;font-size:.85rem;padding:8px 10px;outline:none;transition:border-color .15s}
778
- .monkey-input:focus,.monkey-textarea:focus{border-color:#22c55e}
779
- .monkey-textarea{width:100%;min-height:92px;resize:vertical;line-height:1.45;margin-bottom:10px}
780
- .monkey-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
781
- .monkey-status{font-family:'Courier New',monospace;font-size:.78rem;color:#94a3b8}
782
- .monkey-result{display:none;margin-top:12px;background:#020b0a;border:1px solid #134e4a;border-radius:8px;padding:10px;white-space:pre-wrap;word-break:break-word;font-family:'Courier New',monospace;font-size:.82rem;color:#bbf7d0;max-height:240px;overflow:auto}
783
- .monkey-result.open{display:block}
784
- @media (max-width:720px){.monkey-panel{width:100vw}.monkey-grid{grid-template-columns:1fr}}
769
+ .tintin-tab{position:fixed;top:50%;right:0;transform:translateY(-50%);z-index:81;writing-mode:vertical-rl;text-orientation:mixed;background:linear-gradient(180deg,#103c2f,#0f2f3f);color:#86efac;border:1px solid #166534;border-right:none;border-radius:8px 0 0 8px;padding:14px 6px;font-size:.78rem;font-weight:700;cursor:pointer;letter-spacing:.5px;transition:all .2s}
770
+ .tintin-tab:hover{background:linear-gradient(180deg,#14532d,#155e75);color:#bbf7d0;padding-right:10px}
771
+ .tintin-tab.active{background:#081c1a;border-color:#22c55e;color:#bbf7d0}
772
+ .tintin-panel{position:fixed;top:0;right:-440px;bottom:0;z-index:80;width:min(420px,calc(100vw - 24px));background:#081c1a;border-left:1px solid #14532d;padding:0;box-shadow:-22px 0 60px rgba(0,0,0,.42);display:flex;flex-direction:column;transition:right .25s ease}
773
+ .tintin-panel.open{right:0}
774
+ .tintin-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:.8rem}
775
+ .tintin-title{font-size:.95rem;font-weight:700;color:#dcfce7}
776
+ .tintin-sub{font-size:.78rem;color:#6ee7b7;margin-top:2px}
777
+ .tintin-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px}
778
+ .tintin-field{display:flex;flex-direction:column;gap:4px}
779
+ .tintin-field label{font-size:.72rem;color:#94a3b8;text-transform:uppercase;letter-spacing:.04em;font-weight:700}
780
+ .tintin-input,.tintin-textarea{background:#031312;border:1px solid #14532d;border-radius:6px;color:#e2e8f0;font-family:'Courier New',monospace;font-size:.85rem;padding:8px 10px;outline:none;transition:border-color .15s}
781
+ .tintin-input:focus,.tintin-textarea:focus{border-color:#22c55e}
782
+ .tintin-textarea{width:100%;min-height:92px;resize:vertical;line-height:1.45;margin-bottom:10px}
783
+ .tintin-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
784
+ .tintin-status{font-family:'Courier New',monospace;font-size:.78rem;color:#94a3b8}
785
+ .tintin-result{display:none;margin-top:12px;background:#020b0a;border:1px solid #134e4a;border-radius:8px;padding:10px;white-space:pre-wrap;word-break:break-word;font-family:'Courier New',monospace;font-size:.82rem;color:#bbf7d0;max-height:240px;overflow:auto}
786
+ .tintin-result.open{display:block}
787
+ @media (max-width:720px){.tintin-panel{width:100vw}.tintin-grid{grid-template-columns:1fr}}
785
788
  .mcp-row{display:flex;align-items:center;gap:8px;margin-bottom:8px}
786
789
  .mcp-label{font-size:.72rem;color:#64748b;min-width:80px;text-transform:uppercase;letter-spacing:.5px;font-weight:600}
787
790
  .mcp-val{flex:1;font-family:'Courier New',monospace;font-size:.82rem;color:#60a5fa;background:#0a0f1a;border:1px solid #1e3a5f;border-radius:4px;padding:6px 10px;word-break:break-all;user-select:all}
@@ -950,7 +953,6 @@ function dashboardHtml(port, whitelist, isStaged = false, initWriteToken = null)
950
953
  <button class="btn-refresh" onclick="loadServices()">↻ Refresh</button>
951
954
  <button class="btn-add" onclick="toggleAddService()">+ Add Service</button>
952
955
  <button class="btn-check" id="check-btn" onclick="checkAll()">⬤ Check All</button>
953
- <button class="btn-monkey" id="monkey-btn" onclick="toggleMonkeyPanel()" title="Open Monkey local CLI dispatch test panel">Monkey</button>
954
956
  <button class="btn-ccandme" id="ccandme-btn" onclick="launchCCandMe()" title="Launch CCandMe — 4-pane WezTerm: Claude + Codex + Me">⚡ CCandMe</button>
955
957
  <button class="btn-lock" id="unlock-writes-btn" onclick="unlockWrites()" title="Enter password to enable saving changes this browser session (needed after a daemon restart when auto-unlocked via --pw)">🔓 Unlock Writes</button>
956
958
  <button class="btn-lock" onclick="lockVault()">🔒 Lock</button>
@@ -1079,31 +1081,35 @@ function dashboardHtml(port, whitelist, isStaged = false, initWriteToken = null)
1079
1081
  </div>
1080
1082
  </div>
1081
1083
 
1082
- <div class="monkey-panel" id="monkey-panel">
1083
- <div class="monkey-head">
1084
- <div>
1085
- <div class="monkey-title">Monkey local CLI dispatch</div>
1086
- <div class="monkey-sub">Tests the same local clauth path the browser sidebar will use: /monkey/dispatch → Claude CLI → /monkey/dispatch/:job_id.</div>
1084
+ <div class="tintin-tab" id="tintin-tab" onclick="toggleTinTinPanel()">TinTin</div>
1085
+ <div class="tintin-panel" id="tintin-panel">
1086
+ <div class="tintin-head" style="padding:12px 16px;border-bottom:1px solid #14532d;flex-shrink:0">
1087
+ <div style="display:flex;align-items:center;justify-content:space-between">
1088
+ <div class="tintin-title">TinTin</div>
1089
+ <button class="btn-cancel" onclick="toggleTinTinPanel()" style="font-size:16px;padding:2px 6px">x</button>
1087
1090
  </div>
1088
- <button class="btn-cancel" onclick="toggleMonkeyPanel()">Close</button>
1091
+ <div class="tintin-sub">claude-sonnet-4-6 · clauth CLI dispatch</div>
1089
1092
  </div>
1090
- <div class="monkey-grid">
1091
- <div class="monkey-field">
1092
- <label>App slug</label>
1093
- <input class="monkey-input" id="monkey-app" value="clauth-dashboard" spellcheck="false" autocomplete="off">
1093
+ <div id="tintin-messages" style="flex:1;min-height:0;overflow-y:auto;padding:12px 16px;display:flex;flex-direction:column;gap:10px">
1094
+ <div style="font-size:.78rem;color:#6ee7b7;font-style:italic">Ask anything. Runs a Claude CLI agent with full clauth + repo context.</div>
1095
+ </div>
1096
+ <div style="padding:10px 16px;border-top:1px solid #14532d;flex-shrink:0">
1097
+ <div class="tintin-grid" style="margin-bottom:8px">
1098
+ <div class="tintin-field">
1099
+ <label>CWD</label>
1100
+ <input class="tintin-input" id="tintin-cwd" value="C:\\Dev\\regen-root" spellcheck="false" autocomplete="off">
1101
+ </div>
1102
+ <div class="tintin-field">
1103
+ <label>App</label>
1104
+ <input class="tintin-input" id="tintin-app" value="clauth" spellcheck="false" autocomplete="off">
1105
+ </div>
1094
1106
  </div>
1095
- <div class="monkey-field">
1096
- <label>CWD</label>
1097
- <input class="monkey-input" id="monkey-cwd" value="C:\\Dev\\regen-root" spellcheck="false" autocomplete="off">
1107
+ <textarea class="tintin-textarea" id="tintin-prompt" spellcheck="false" placeholder="Ask TinTin..." style="min-height:64px;margin-bottom:8px"></textarea>
1108
+ <div style="display:flex;gap:8px;align-items:center">
1109
+ <button class="btn-tintin" id="tintin-send" onclick="sendTinTinMessage()" style="flex:1">Send</button>
1110
+ <span class="tintin-status" id="tintin-status">idle</span>
1098
1111
  </div>
1099
1112
  </div>
1100
- <textarea class="monkey-textarea" id="monkey-prompt" spellcheck="false">Reply exactly: monkey-dashboard-ok</textarea>
1101
- <div class="monkey-actions">
1102
- <button class="btn-monkey" id="monkey-send" onclick="sendMonkeyDashboardMessage()">Dispatch CLI</button>
1103
- <button class="btn-check" onclick="fillMonkeySmoke()" style="padding:7px 12px">Smoke Prompt</button>
1104
- <span class="monkey-status" id="monkey-status">idle</span>
1105
- </div>
1106
- <div class="monkey-result" id="monkey-result"></div>
1107
1113
  </div>
1108
1114
 
1109
1115
 
@@ -1505,52 +1511,62 @@ async function launchCCandMe() {
1505
1511
  }
1506
1512
  }
1507
1513
 
1508
- // ── Monkey local CLI dispatch test panel ──
1509
- let monkeyPollTimer = null;
1514
+ // ── TinTin local CLI dispatch sidebar ──
1515
+ let tintinPollTimer = null;
1510
1516
 
1511
- function toggleMonkeyPanel() {
1512
- const panel = document.getElementById("monkey-panel");
1517
+ function toggleTinTinPanel() {
1518
+ const panel = document.getElementById("tintin-panel");
1519
+ const tab = document.getElementById("tintin-tab");
1513
1520
  if (!panel) return;
1514
1521
  panel.classList.toggle("open");
1522
+ if (tab) tab.classList.toggle("active");
1515
1523
  }
1516
1524
 
1517
- function fillMonkeySmoke() {
1518
- const prompt = document.getElementById("monkey-prompt");
1519
- const app = document.getElementById("monkey-app");
1525
+ function fillTinTinSmoke() {
1526
+ const prompt = document.getElementById("tintin-prompt");
1527
+ const app = document.getElementById("tintin-app");
1520
1528
  if (app) app.value = "clauth-dashboard";
1521
- if (prompt) prompt.value = "Reply exactly: monkey-dashboard-ok";
1529
+ if (prompt) prompt.value = "Reply exactly: tintin-dashboard-ok";
1522
1530
  }
1523
1531
 
1524
- function setMonkeyStatus(text) {
1525
- const el = document.getElementById("monkey-status");
1532
+ function setTinTinStatus(text) {
1533
+ const el = document.getElementById("tintin-status");
1526
1534
  if (el) el.textContent = text || "";
1527
1535
  }
1528
1536
 
1529
- function setMonkeyResult(text, open) {
1530
- const el = document.getElementById("monkey-result");
1531
- if (!el) return;
1532
- el.textContent = text || "";
1533
- if (open) el.classList.add("open");
1534
- else el.classList.remove("open");
1537
+ function appendTinTinMessage(role, text) {
1538
+ const container = document.getElementById("tintin-messages");
1539
+ if (!container || !text) return;
1540
+ const bubble = document.createElement("div");
1541
+ bubble.style.cssText = role === "user"
1542
+ ? "background:#14532d;border:1px solid #166534;border-radius:8px;padding:8px 10px;font-size:.82rem;color:#bbf7d0;white-space:pre-wrap;word-break:break-word;align-self:flex-end;max-width:90%"
1543
+ : "background:#0a1f1a;border:1px solid #134e4a;border-radius:8px;padding:8px 10px;font-size:.82rem;color:#86efac;font-family:'Courier New',monospace;white-space:pre-wrap;word-break:break-word;max-width:95%;max-height:300px;overflow:auto";
1544
+ bubble.textContent = text;
1545
+ container.appendChild(bubble);
1546
+ container.scrollTop = container.scrollHeight;
1535
1547
  }
1536
1548
 
1537
- async function sendMonkeyDashboardMessage() {
1538
- const sendBtn = document.getElementById("monkey-send");
1539
- const promptEl = document.getElementById("monkey-prompt");
1540
- const appEl = document.getElementById("monkey-app");
1541
- const cwdEl = document.getElementById("monkey-cwd");
1549
+ function setTinTinResult(text, open) {
1550
+ if (open && text) appendTinTinMessage("assistant", text);
1551
+ }
1552
+
1553
+ async function sendTinTinMessage() {
1554
+ const sendBtn = document.getElementById("tintin-send");
1555
+ const promptEl = document.getElementById("tintin-prompt");
1556
+ const appEl = document.getElementById("tintin-app");
1557
+ const cwdEl = document.getElementById("tintin-cwd");
1542
1558
  const prompt = (promptEl && promptEl.value || "").trim();
1543
1559
  const appSlug = (appEl && appEl.value || "clauth-dashboard").trim() || "clauth-dashboard";
1544
1560
  const cwd = (cwdEl && cwdEl.value || "").trim();
1545
1561
  if (!prompt) {
1546
- setMonkeyStatus("prompt required");
1562
+ setTinTinStatus("prompt required");
1547
1563
  return;
1548
1564
  }
1549
- if (monkeyPollTimer) {
1550
- clearTimeout(monkeyPollTimer);
1551
- monkeyPollTimer = null;
1565
+ if (tintinPollTimer) {
1566
+ clearTimeout(tintinPollTimer);
1567
+ tintinPollTimer = null;
1552
1568
  }
1553
- const jobId = "monkey-dashboard-" + Date.now();
1569
+ const jobId = "tintin-" + Date.now();
1554
1570
  const body = {
1555
1571
  prompt,
1556
1572
  job_id: jobId,
@@ -1558,14 +1574,15 @@ async function sendMonkeyDashboardMessage() {
1558
1574
  agent_context: {
1559
1575
  app: { slug: appSlug, route: "/clauth-dashboard", origin: window.location.origin },
1560
1576
  repo: { root: cwd, cwd },
1561
- runtime: { agent: "clauth-cli", requested_by: "clauth-dashboard" },
1577
+ runtime: { agent: "clauth-cli", requested_by: "clauth-dashboard", model: "claude-sonnet-4-6" },
1562
1578
  task: { intent: "general_chat", thread_id: jobId }
1563
1579
  }
1564
1580
  };
1565
1581
 
1582
+ appendTinTinMessage("user", prompt);
1583
+ if (promptEl) promptEl.value = "";
1566
1584
  if (sendBtn) { sendBtn.disabled = true; sendBtn.textContent = "Dispatching..."; }
1567
- setMonkeyStatus("dispatching " + jobId);
1568
- setMonkeyResult("", false);
1585
+ setTinTinStatus("dispatching");
1569
1586
  try {
1570
1587
  const response = await fetch(BASE + "/monkey/dispatch", {
1571
1588
  method: "POST",
@@ -1574,48 +1591,41 @@ async function sendMonkeyDashboardMessage() {
1574
1591
  });
1575
1592
  const result = await response.json();
1576
1593
  if (!response.ok || result.error) {
1577
- setMonkeyStatus("dispatch failed");
1578
- setMonkeyResult(JSON.stringify(result, null, 2), true);
1594
+ setTinTinStatus("dispatch failed");
1595
+ setTinTinResult(JSON.stringify(result, null, 2), true);
1579
1596
  return;
1580
1597
  }
1581
- setMonkeyStatus("spawned pid " + result.pid + " - polling");
1582
- pollMonkeyDashboardJob(jobId, 0);
1598
+ setTinTinStatus("spawned pid " + result.pid + " - polling");
1599
+ pollTinTinJob(jobId, 0);
1583
1600
  } catch (err) {
1584
- setMonkeyStatus("dispatch error");
1585
- setMonkeyResult(err && err.message ? err.message : String(err), true);
1601
+ setTinTinStatus("dispatch error");
1602
+ setTinTinResult(err && err.message ? err.message : String(err), true);
1586
1603
  } finally {
1587
- if (sendBtn) { sendBtn.disabled = false; sendBtn.textContent = "Dispatch CLI"; }
1604
+ if (sendBtn) { sendBtn.disabled = false; sendBtn.textContent = "Dispatch"; }
1588
1605
  }
1589
1606
  }
1590
1607
 
1591
- async function pollMonkeyDashboardJob(jobId, attempt) {
1608
+ async function pollTinTinJob(jobId, attempt) {
1592
1609
  try {
1593
1610
  const response = await fetch(BASE + "/monkey/dispatch/" + encodeURIComponent(jobId), { cache: "no-store" });
1594
1611
  const job = await response.json();
1595
1612
  if (!response.ok || job.error) {
1596
- setMonkeyStatus("job lookup failed");
1597
- setMonkeyResult(JSON.stringify(job, null, 2), true);
1613
+ setTinTinStatus("job lookup failed");
1614
+ setTinTinResult(JSON.stringify(job, null, 2), true);
1598
1615
  return;
1599
1616
  }
1600
1617
  if (job.status === "running" && attempt < 60) {
1601
- setMonkeyStatus("running pid " + (job.pid || "?") + " - " + (attempt + 1));
1602
- monkeyPollTimer = setTimeout(function() { pollMonkeyDashboardJob(jobId, attempt + 1); }, 1500);
1618
+ setTinTinStatus("running pid " + (job.pid || "?") + " - " + (attempt + 1));
1619
+ tintinPollTimer = setTimeout(function() { pollTinTinJob(jobId, attempt + 1); }, 1500);
1603
1620
  return;
1604
1621
  }
1605
- setMonkeyStatus(job.status + " exit " + job.exit_code);
1606
- const out = [
1607
- "status: " + job.status,
1608
- "job: " + jobId,
1609
- "cwd: " + (job.cwd || ""),
1610
- "",
1611
- "stdout:",
1612
- job.stdout || "",
1613
- job.stderr ? "\\nstderr:\\n" + job.stderr : ""
1614
- ].join("\\n");
1615
- setMonkeyResult(out, true);
1622
+ setTinTinStatus(job.status === "completed" ? "done" : job.status);
1623
+ const out = (job.stdout || "").trim();
1624
+ if (out) appendTinTinMessage("assistant", out);
1625
+ if (job.stderr && job.stderr.trim()) appendTinTinMessage("assistant", "stderr: " + job.stderr.trim());
1616
1626
  } catch (err) {
1617
- setMonkeyStatus("poll error");
1618
- setMonkeyResult(err && err.message ? err.message : String(err), true);
1627
+ setTinTinStatus("poll error");
1628
+ setTinTinResult(err && err.message ? err.message : String(err), true);
1619
1629
  }
1620
1630
  }
1621
1631
 
@@ -7892,20 +7902,20 @@ function buildMonkeyDispatchPrompt({ prompt, job_id, agent_context }) {
7892
7902
  const normalized = normalizeAgentContext(agent_context);
7893
7903
  const jobInstruction = job_id
7894
7904
  ? [
7895
- `Monkey job id: ${job_id}`,
7905
+ `TinTin job id: ${job_id}`,
7896
7906
  "If the prompt does not contain all job details, use clauth at http://127.0.0.1:52437 to fetch exact credentials and query the app database/API directly.",
7897
7907
  "Do not assume agent MCP/plugin tools are available to this spawned CLI process.",
7898
7908
  ].join("\n")
7899
7909
  : "";
7900
7910
 
7901
7911
  const body = prompt || [
7902
- "Process this Monkey job using the provided agent context.",
7912
+ "Process this TinTin job using the provided agent context.",
7903
7913
  jobInstruction,
7904
7914
  "Find the job payload from the consuming app's declared data path before making changes.",
7905
7915
  ].filter(Boolean).join("\n\n");
7906
7916
 
7907
7917
  return [
7908
- "You are a clauth-spawned Monkey CLI worker.",
7918
+ "You are a clauth-spawned TinTin CLI agent (model: claude-sonnet-4-6).",
7909
7919
  "Agent context setup follows. Treat it as the runtime contract for this task.",
7910
7920
  "```json",
7911
7921
  JSON.stringify(normalized, null, 2),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/clauth",
3
- "version": "1.19.2",
3
+ "version": "1.19.4",
4
4
  "description": "Hardware-bound credential vault for the LIFEAI infrastructure stack",
5
5
  "type": "module",
6
6
  "bin": {