@rajat-rastogi/maestro 0.6.0 → 0.7.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.
@@ -503,6 +503,15 @@ function registerSessionsIpc(sessionManager2) {
503
503
  electron.ipcMain.handle("sessions:resize", async (_e, id, cols, rows) => {
504
504
  sessionManager2.resize(id, cols, rows);
505
505
  });
506
+ electron.ipcMain.handle("sessions:savedList", async () => {
507
+ return sessionManager2.listSaved();
508
+ });
509
+ electron.ipcMain.handle("sessions:savedResume", async (_e, ids, resumeAI) => {
510
+ return sessionManager2.resumeSaved(ids, resumeAI);
511
+ });
512
+ electron.ipcMain.handle("sessions:savedDismiss", async () => {
513
+ sessionManager2.dismissSaved();
514
+ });
506
515
  }
507
516
  const execAsync$2 = util.promisify(child_process.exec);
508
517
  class AgentConnectionPool {
@@ -1184,11 +1193,20 @@ class LocalPtyAdapter {
1184
1193
  } catch {
1185
1194
  }
1186
1195
  }
1187
- autoLaunch(provider) {
1196
+ autoLaunch(provider, skipPermissions, resumeAI) {
1188
1197
  if (provider === "claude") {
1189
- setTimeout(() => this.write("claude\r"), 800);
1198
+ const flags = [
1199
+ resumeAI ? "--continue" : "",
1200
+ skipPermissions ? "--dangerously-skip-permissions" : ""
1201
+ ].filter(Boolean).join(" ");
1202
+ setTimeout(() => this.write(`claude${flags ? " " + flags : ""}\r`), 800);
1190
1203
  } else if (provider === "copilot") {
1191
- setTimeout(() => this.write("copilot --output-format json\r"), 800);
1204
+ const flags = [
1205
+ "--output-format json",
1206
+ resumeAI ? "--continue" : "",
1207
+ skipPermissions ? "--yolo" : ""
1208
+ ].filter(Boolean).join(" ");
1209
+ setTimeout(() => this.write(`copilot ${flags}\r`), 800);
1192
1210
  }
1193
1211
  }
1194
1212
  }
@@ -1383,11 +1401,20 @@ class SshPtyAdapter {
1383
1401
  this.sshClient = null;
1384
1402
  this.devtunnelProc = null;
1385
1403
  }
1386
- autoLaunch(provider) {
1404
+ autoLaunch(provider, skipPermissions, resumeAI) {
1387
1405
  if (provider === "claude") {
1388
- setTimeout(() => this.write("claude\r"), 1200);
1406
+ const flags = [
1407
+ resumeAI ? "--continue" : "",
1408
+ skipPermissions ? "--dangerously-skip-permissions" : ""
1409
+ ].filter(Boolean).join(" ");
1410
+ setTimeout(() => this.write(`claude${flags ? " " + flags : ""}\r`), 1200);
1389
1411
  } else if (provider === "copilot") {
1390
- setTimeout(() => this.write("copilot --output-format json\r"), 1200);
1412
+ const flags = [
1413
+ "--output-format json",
1414
+ resumeAI ? "--continue" : "",
1415
+ skipPermissions ? "--yolo" : ""
1416
+ ].filter(Boolean).join(" ");
1417
+ setTimeout(() => this.write(`copilot ${flags}\r`), 1200);
1391
1418
  }
1392
1419
  }
1393
1420
  }
@@ -1525,11 +1552,20 @@ class AgentPtyAdapter {
1525
1552
  this.ws.send(JSON.stringify({ type: "destroy", id: this.sessionId }));
1526
1553
  }
1527
1554
  }
1528
- autoLaunch(provider) {
1555
+ autoLaunch(provider, skipPermissions, resumeAI) {
1529
1556
  if (provider === "claude") {
1530
- setTimeout(() => this.write("claude\r"), 600);
1557
+ const flags = [
1558
+ resumeAI ? "--continue" : "",
1559
+ skipPermissions ? "--dangerously-skip-permissions" : ""
1560
+ ].filter(Boolean).join(" ");
1561
+ setTimeout(() => this.write(`claude${flags ? " " + flags : ""}\r`), 600);
1531
1562
  } else if (provider === "copilot") {
1532
- setTimeout(() => this.write("copilot --output-format json\r"), 600);
1563
+ const flags = [
1564
+ "--output-format json",
1565
+ resumeAI ? "--continue" : "",
1566
+ skipPermissions ? "--yolo" : ""
1567
+ ].filter(Boolean).join(" ");
1568
+ setTimeout(() => this.write(`copilot ${flags}\r`), 600);
1533
1569
  }
1534
1570
  }
1535
1571
  }
@@ -1832,9 +1868,65 @@ class SessionManager {
1832
1868
  entries = /* @__PURE__ */ new Map();
1833
1869
  machineManager;
1834
1870
  push;
1871
+ savedPath;
1872
+ savedSessions = [];
1835
1873
  constructor(machineManager2, push) {
1836
1874
  this.machineManager = machineManager2;
1837
1875
  this.push = push;
1876
+ this.savedPath = path__namespace.join(electron.app.getPath("userData"), "saved-sessions.json");
1877
+ this.loadSaved();
1878
+ }
1879
+ loadSaved() {
1880
+ try {
1881
+ const data = fs__namespace.readFileSync(this.savedPath, "utf8");
1882
+ this.savedSessions = JSON.parse(data);
1883
+ console.log(`[SessionManager] Loaded ${this.savedSessions.length} saved sessions`);
1884
+ } catch {
1885
+ this.savedSessions = [];
1886
+ }
1887
+ }
1888
+ saveToDisk() {
1889
+ try {
1890
+ fs__namespace.writeFileSync(this.savedPath, JSON.stringify(this.savedSessions, null, 2), "utf8");
1891
+ } catch (err) {
1892
+ console.error("[SessionManager] Failed to save sessions:", err);
1893
+ }
1894
+ }
1895
+ listSaved() {
1896
+ return this.savedSessions;
1897
+ }
1898
+ dismissSaved() {
1899
+ this.savedSessions = [];
1900
+ this.saveToDisk();
1901
+ }
1902
+ async resumeSaved(ids, resumeAI) {
1903
+ const resumed = [];
1904
+ const skipped = [];
1905
+ for (const saved of this.savedSessions.filter((s) => ids.includes(s.id))) {
1906
+ const machine = this.machineManager.getById(saved.machineId);
1907
+ if (saved.machineId !== "local" && (!machine || machine.status === "offline")) {
1908
+ skipped.push(saved.name);
1909
+ continue;
1910
+ }
1911
+ try {
1912
+ const session = await this.create({
1913
+ name: saved.name,
1914
+ machineId: saved.machineId,
1915
+ provider: saved.provider,
1916
+ workingDirectory: saved.workingDirectory,
1917
+ tags: saved.tags,
1918
+ skipPermissions: saved.skipPermissions,
1919
+ resumeAI: resumeAI && saved.provider !== "none"
1920
+ });
1921
+ resumed.push(session);
1922
+ } catch (err) {
1923
+ console.error(`[SessionManager] Failed to resume "${saved.name}":`, err);
1924
+ skipped.push(saved.name);
1925
+ }
1926
+ }
1927
+ this.savedSessions = [];
1928
+ this.saveToDisk();
1929
+ return { resumed, skipped };
1838
1930
  }
1839
1931
  list() {
1840
1932
  return Array.from(this.entries.values()).map((e) => ({
@@ -1913,8 +2005,20 @@ class SessionManager {
1913
2005
  });
1914
2006
  monitor.start();
1915
2007
  if (opts.provider !== "none") {
1916
- adapter.autoLaunch(opts.provider);
1917
- }
2008
+ adapter.autoLaunch(opts.provider, opts.skipPermissions, opts.resumeAI);
2009
+ }
2010
+ this.savedSessions = this.savedSessions.filter((s) => s.id !== session.id);
2011
+ this.savedSessions.push({
2012
+ id: session.id,
2013
+ name: session.name,
2014
+ machineId: session.machineId,
2015
+ provider: session.provider,
2016
+ workingDirectory: session.workingDirectory,
2017
+ tags: session.tags,
2018
+ skipPermissions: opts.skipPermissions,
2019
+ savedAt: (/* @__PURE__ */ new Date()).toISOString()
2020
+ });
2021
+ this.saveToDisk();
1918
2022
  return { ...session };
1919
2023
  }
1920
2024
  destroy(id) {
@@ -1923,6 +2027,8 @@ class SessionManager {
1923
2027
  entry.monitor.stop();
1924
2028
  entry.adapter.kill();
1925
2029
  this.entries.delete(id);
2030
+ this.savedSessions = this.savedSessions.filter((s) => s.id !== id);
2031
+ this.saveToDisk();
1926
2032
  }
1927
2033
  rename(id, name) {
1928
2034
  const entry = this.entries.get(id);
@@ -2069,6 +2175,15 @@ electron.app.whenReady().then(() => {
2069
2175
  electron.ipcMain.handle("app:getStartupArgs", () => ({
2070
2176
  planFile: startupPlanFile
2071
2177
  }));
2178
+ electron.ipcMain.handle("app:getVersion", () => {
2179
+ try {
2180
+ const pkgPath = path.join(__dirname, "..", "..", "..", "package.json");
2181
+ const pkg = JSON.parse(fs__namespace.readFileSync(pkgPath, "utf8"));
2182
+ return pkg.version ?? "unknown";
2183
+ } catch {
2184
+ return electron.app.getVersion();
2185
+ }
2186
+ });
2072
2187
  createWindow();
2073
2188
  electron.app.on("activate", () => {
2074
2189
  if (electron.BrowserWindow.getAllWindows().length === 0) {
@@ -55,6 +55,7 @@ electron.contextBridge.exposeInMainWorld("maestro", {
55
55
  },
56
56
  // Read startup args passed from CLI
57
57
  getStartupArgs: () => electron.ipcRenderer.invoke("app:getStartupArgs"),
58
+ getVersion: () => electron.ipcRenderer.invoke("app:getVersion"),
58
59
  // Machine management
59
60
  machines: {
60
61
  list: () => electron.ipcRenderer.invoke("machines:list"),
@@ -84,6 +85,9 @@ electron.contextBridge.exposeInMainWorld("maestro", {
84
85
  acknowledge: (id) => electron.ipcRenderer.invoke("sessions:acknowledge", id),
85
86
  sendInput: (id, data) => electron.ipcRenderer.invoke("sessions:sendInput", id, data),
86
87
  resize: (id, cols, rows) => electron.ipcRenderer.invoke("sessions:resize", id, cols, rows),
88
+ savedList: () => electron.ipcRenderer.invoke("sessions:savedList"),
89
+ savedResume: (ids, resumeAI) => electron.ipcRenderer.invoke("sessions:savedResume", ids, resumeAI),
90
+ savedDismiss: () => electron.ipcRenderer.invoke("sessions:savedDismiss"),
87
91
  onData: (cb) => {
88
92
  const handler = (_, ev) => cb(ev);
89
93
  electron.ipcRenderer.on("sessions:data", handler);