clauder-hub 0.1.21 → 0.1.23

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 (25) hide show
  1. package/package.json +1 -1
  2. package/server/dist/index.js +78 -6
  3. package/web/dist/assets/{MonacoEditor-BTVIBYvB.js → MonacoEditor-CL8dQ4S_.js} +3 -3
  4. package/web/dist/assets/{cssMode-C586Sf_r.js → cssMode-B7SnUu3K.js} +1 -1
  5. package/web/dist/assets/{freemarker2-C-cc3Gll.js → freemarker2-C12Idt1V.js} +1 -1
  6. package/web/dist/assets/{handlebars-DvIHaXiS.js → handlebars-DmLRZ5Z6.js} +1 -1
  7. package/web/dist/assets/{html-B6mVPILf.js → html-ZIBJ1Ljb.js} +1 -1
  8. package/web/dist/assets/{htmlMode-DdTtdH0Z.js → htmlMode-DJkp04pp.js} +1 -1
  9. package/web/dist/assets/{index-BQk7iZCf.js → index-BdO16SqL.js} +1 -1
  10. package/web/dist/assets/{index-D7vjfqSK.js → index-C3NdTBDT.js} +82 -82
  11. package/web/dist/assets/index-D2NZ4b9D.css +32 -0
  12. package/web/dist/assets/{javascript-B_oWtDTg.js → javascript-NBDYFbL6.js} +1 -1
  13. package/web/dist/assets/{jsonMode-qce5w2Wk.js → jsonMode-DflxjbAf.js} +1 -1
  14. package/web/dist/assets/{liquid-7IWcrKEP.js → liquid-ilFuRlap.js} +1 -1
  15. package/web/dist/assets/{lspLanguageFeatures-CmmvUFJp.js → lspLanguageFeatures-BXNfsqvp.js} +1 -1
  16. package/web/dist/assets/{mdx-C7aHCLPx.js → mdx-Jf9I7vO6.js} +1 -1
  17. package/web/dist/assets/{python-DM5DwMK7.js → python-Iz5LZz1d.js} +1 -1
  18. package/web/dist/assets/{razor-B7mgUEn8.js → razor-i-xTFJzF.js} +1 -1
  19. package/web/dist/assets/{tsMode-DxSLItWY.js → tsMode-BxwlmeYx.js} +1 -1
  20. package/web/dist/assets/{typescript-ByJ-uQZm.js → typescript-Bz7MFeIA.js} +1 -1
  21. package/web/dist/assets/{workers-CJj-afeH.js → workers-C4RLUiS8.js} +1 -1
  22. package/web/dist/assets/{xml-qEcmYLej.js → xml-ByOI4VuJ.js} +1 -1
  23. package/web/dist/assets/{yaml-DJRPJYdB.js → yaml-Cfnm5kOn.js} +1 -1
  24. package/web/dist/index.html +2 -2
  25. package/web/dist/assets/index-BRBOC-HN.css +0 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clauder-hub",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "A local dashboard that runs, watches and automates the Claude Code sessions of every project on the machine",
5
5
  "license": "MIT",
6
6
  "author": "goldyndevs <goldyndevs@gmail.com>",
@@ -26920,7 +26920,7 @@ function findClaudeCode() {
26920
26920
  async function check() {
26921
26921
  cached = void 0;
26922
26922
  const found = findClaudeCode();
26923
- const base = { path: found, version: null, loggedIn: null, account: null, checkedAt: Date.now() };
26923
+ const base = { path: found, version: null, loggedIn: null, account: null, authMethod: null, org: null, plan: null, loginExpiresAt: null, checkedAt: Date.now() };
26924
26924
  if (!found) {
26925
26925
  return { ...base, problem: "missing", message: "Claude Code is not installed on this machine.", fix: "npm i -g @anthropic-ai/claude-code" };
26926
26926
  }
@@ -26931,10 +26931,16 @@ async function check() {
26931
26931
  const auth = await run(found, ["auth", "status"]);
26932
26932
  let loggedIn = null;
26933
26933
  let account = null;
26934
+ const about = { authMethod: null, org: null, plan: null, loginExpiresAt: null };
26935
+ const text = (value) => typeof value === "string" && value ? value : null;
26934
26936
  try {
26935
26937
  const parsed = JSON.parse(auth.out);
26936
26938
  if (typeof parsed.loggedIn === "boolean") loggedIn = parsed.loggedIn;
26937
- account = parsed.email ?? parsed.authMethod ?? null;
26939
+ account = text(parsed.email) ?? text(parsed.authMethod);
26940
+ about.authMethod = text(parsed.authMethod);
26941
+ about.org = text(parsed.orgName);
26942
+ about.plan = text(parsed.subscriptionType);
26943
+ about.loginExpiresAt = text(parsed.loginExpiresAt);
26938
26944
  } catch {
26939
26945
  }
26940
26946
  const signedOut = loggedIn === false;
@@ -26943,6 +26949,7 @@ async function check() {
26943
26949
  version: version.out.trim().split(/\s/)[0] || null,
26944
26950
  loggedIn,
26945
26951
  account,
26952
+ ...about,
26946
26953
  problem: signedOut ? "signedOut" : null,
26947
26954
  message: signedOut ? "Claude Code is installed but not signed in." : null,
26948
26955
  fix: signedOut ? "claude auth login" : null
@@ -32399,7 +32406,10 @@ function waitForExit(terminal, timeoutMs = 1e4) {
32399
32406
  });
32400
32407
  }
32401
32408
  function killAll() {
32402
- for (const terminal of terminals.values()) killTerminal(terminal);
32409
+ for (const terminal of terminals.values()) {
32410
+ terminal.stopping = true;
32411
+ killTerminal(terminal);
32412
+ }
32403
32413
  }
32404
32414
  function killProjectTerminals(projectId) {
32405
32415
  const killed = [...terminals.values()].filter((terminal) => terminal.projectId === projectId);
@@ -34231,7 +34241,7 @@ function startNext() {
34231
34241
  }
34232
34242
  function watchRunExits() {
34233
34243
  onTerminalExit((terminal) => {
34234
- if (terminal.restarting) return;
34244
+ if (terminal.restarting || terminal.stopping) return;
34235
34245
  const row = getSessionRow(terminal.sessionId);
34236
34246
  if (row && row.status !== "done") setSessionStatus(terminal.sessionId, "exited");
34237
34247
  if (row?.run_id) finishRun(row.run_id, row.status === "done" ? "done" : "exited");
@@ -35982,6 +35992,60 @@ var init_watchdog = __esm({
35982
35992
  }
35983
35993
  });
35984
35994
 
35995
+ // server/src/resume.ts
35996
+ function resumeOnStart() {
35997
+ const row = globalDb.prepare("SELECT value FROM hub_settings WHERE key = 'resumeOnStart'").get();
35998
+ return row?.value !== "0";
35999
+ }
36000
+ function setResumeOnStart(on) {
36001
+ globalDb.prepare("INSERT INTO hub_settings (key, value, updated_at) VALUES ('resumeOnStart', ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at").run(on ? "1" : "0", now());
36002
+ return on;
36003
+ }
36004
+ function leftRunning() {
36005
+ return db.prepare("SELECT id, run_id FROM sessions WHERE status IN ('running', 'waiting')").all().map((row) => ({
36006
+ id: row.id,
36007
+ runId: row.run_id
36008
+ }));
36009
+ }
36010
+ function resumeLeftRunning(list) {
36011
+ if (!list.length || !resumeOnStart()) return;
36012
+ const worth = list.filter((item) => transcriptMtime(item.id) > 0);
36013
+ if (!worth.length) return;
36014
+ console.log(` resume : ${currentProject().name}: ${worth.length} session(s) that were running when the hub stopped`);
36015
+ worth.forEach((item, index) => {
36016
+ setTimeout(
36017
+ bindProject(() => {
36018
+ try {
36019
+ if (terminalForSession(item.id)) return;
36020
+ if (item.runId) resumeRun(item.runId);
36021
+ else startSession({ resumeId: item.id });
36022
+ } catch (error) {
36023
+ console.error(` resume : ${item.id.slice(0, 8)} could not be resumed: ${error.message}`);
36024
+ }
36025
+ }),
36026
+ 1500 + index * 800
36027
+ );
36028
+ });
36029
+ }
36030
+ var init_resume = __esm({
36031
+ "server/src/resume.ts"() {
36032
+ "use strict";
36033
+ init_context();
36034
+ init_db();
36035
+ init_jobs();
36036
+ init_sessions();
36037
+ init_terminals();
36038
+ init_transcripts();
36039
+ globalDb.exec(`
36040
+ CREATE TABLE IF NOT EXISTS hub_settings (
36041
+ key TEXT PRIMARY KEY,
36042
+ value TEXT NOT NULL,
36043
+ updated_at TEXT NOT NULL
36044
+ );
36045
+ `);
36046
+ }
36047
+ });
36048
+
35985
36049
  // server/src/projects.ts
35986
36050
  var projects_exports = {};
35987
36051
  __export(projects_exports, {
@@ -36026,9 +36090,11 @@ function bootGlobal() {
36026
36090
  db: openProjectDb(path13.join(root2, "hub.db"))
36027
36091
  };
36028
36092
  const stops = withProject(project, () => {
36093
+ const left = leftRunning();
36029
36094
  recoverRuns();
36030
36095
  const list = [startTranscriptWatcher(), startInteractionSweeper(), startWatchdog(), stopChannels];
36031
36096
  startChannels({ device: false });
36097
+ resumeLeftRunning(left);
36032
36098
  return list;
36033
36099
  });
36034
36100
  global2 = { project, stops };
@@ -36083,6 +36149,7 @@ function boot(row) {
36083
36149
  const stops = [];
36084
36150
  try {
36085
36151
  withProject(project, () => {
36152
+ const left = leftRunning();
36086
36153
  const stranded = recoverRuns();
36087
36154
  if (stranded) console.log(` note : ${row.name}: ${stranded} queued run(s) were running when the hub last stopped`);
36088
36155
  stops.push(startTranscriptWatcher(), startInteractionSweeper(), startWatchdog());
@@ -36091,6 +36158,7 @@ function boot(row) {
36091
36158
  stops.push(stopScheduler);
36092
36159
  startScheduler();
36093
36160
  advance();
36161
+ resumeLeftRunning(left);
36094
36162
  });
36095
36163
  } catch (error) {
36096
36164
  withProject(project, () => {
@@ -36168,6 +36236,7 @@ var init_projects = __esm({
36168
36236
  init_interactions();
36169
36237
  init_watchdog();
36170
36238
  init_jobs();
36239
+ init_resume();
36171
36240
  init_paths();
36172
36241
  init_terminals();
36173
36242
  init_transcripts();
@@ -38226,6 +38295,7 @@ init_paths();
38226
38295
  init_projects();
38227
38296
  init_prompts();
38228
38297
  init_sessions();
38298
+ init_resume();
38229
38299
  init_terminals();
38230
38300
  init_purposes();
38231
38301
  init_sessionFiles();
@@ -38350,6 +38420,8 @@ hubApi.get(
38350
38420
  () => acrossProjects((info) => withPresentation(listInteractions({ status: "open", limit: 100 })).map((item) => ({ ...item, project: { id: info.id, name: info.name } }))).flat().sort((a, b2) => b2.createdAt.localeCompare(a.createdAt))
38351
38421
  )
38352
38422
  );
38423
+ hubApi.get("/hub/resume-on-start", wrap2(() => ({ on: resumeOnStart() })));
38424
+ hubApi.put("/hub/resume-on-start", wrap2((req) => ({ on: setResumeOnStart(req.body?.on !== false) })));
38353
38425
  hubApi.put("/global/muted/:id", wrap2((req) => ({ muted: setMuted(req.params.id, req.body?.muted === true) })));
38354
38426
  hubApi.delete("/projects/:id", wrap2((req) => removeProject(req.params.id)));
38355
38427
  hubApi.get(
@@ -38860,7 +38932,7 @@ server.on("upgrade", (req, socket, head) => {
38860
38932
  sockets.handleUpgrade(req, socket, head, (ws) => attachClient(terminal, ws));
38861
38933
  });
38862
38934
  onTerminalExit((terminal) => cleanRunFiles(terminal.token));
38863
- onTerminalExit((terminal) => closeOpen(terminal.sessionId, "exit"));
38935
+ onTerminalExit((terminal) => !terminal.stopping && closeOpen(terminal.sessionId, "exit"));
38864
38936
  watchRunExits();
38865
38937
  console.log(`
38866
38938
  \u2733\uFE0F Clauder Hub`);
@@ -38889,7 +38961,7 @@ console.log(` ${underDev ? "api " : "url "} : http://localhost:${actualPo
38889
38961
  if (underDev) console.log(` open : http://localhost:${webPort}${opened}`);
38890
38962
  else if (opened) console.log(` open : http://localhost:${actualPort}${opened}`);
38891
38963
  console.log(`
38892
- Every project's sessions, cron jobs and webhooks run as long as this process. Ctrl+C stops the hub and them.
38964
+ Every project's sessions, cron jobs and webhooks run as long as this process. Ctrl+C stops the hub and them; they resume at its next start (a switch on the Global page).
38893
38965
  `);
38894
38966
  var stopping = false;
38895
38967
  for (const signal of ["SIGINT", "SIGTERM"]) {