@rubytech/taskmaster 1.0.30 → 1.0.31

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.
@@ -0,0 +1,2 @@
1
+ async function l(n){if(!(!n.client||!n.connected)&&!n.uninstallBusy){n.uninstallBusy=!0,n.uninstallError=null,n.requestUpdate?.();try{await n.client.request("system.uninstall",{scopes:["service","state","workspace"],purge:!0}),n.uninstallDone=!0}catch{n.uninstallDone=!0}finally{n.uninstallBusy=!1,n.requestUpdate?.()}}}export{l as runUninstall};
2
+ //# sourceMappingURL=uninstall-mUk7IPTt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall-mUk7IPTt.js","sources":["../../../ui/src/ui/controllers/uninstall.ts"],"sourcesContent":["/**\n * Uninstall controller for the setup page.\n *\n * Calls system.uninstall RPC then handles the expected disconnect\n * (the gateway exits after removing itself).\n */\n\nexport interface UninstallState {\n client: { request: (method: string, params: unknown) => Promise<unknown> } | null;\n connected: boolean;\n uninstallConfirm: boolean;\n uninstallBusy: boolean;\n uninstallDone: boolean;\n uninstallError: string | null;\n uninstallConfirmText: string;\n requestUpdate?: () => void;\n}\n\nexport async function runUninstall(state: UninstallState): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.uninstallBusy) return;\n\n state.uninstallBusy = true;\n state.uninstallError = null;\n state.requestUpdate?.();\n\n try {\n await state.client.request(\"system.uninstall\", {\n scopes: [\"service\", \"state\", \"workspace\"],\n purge: true,\n });\n // Gateway will exit — we may or may not get this response\n state.uninstallDone = true;\n } catch {\n // Expected: WebSocket closes because the gateway exited.\n // If we were busy, that means the uninstall ran — treat as success.\n state.uninstallDone = true;\n } finally {\n state.uninstallBusy = false;\n state.requestUpdate?.();\n }\n}\n\nexport function resetUninstall(state: UninstallState): void {\n state.uninstallConfirm = false;\n state.uninstallBusy = false;\n state.uninstallDone = false;\n state.uninstallError = null;\n state.uninstallConfirmText = \"\";\n state.requestUpdate?.();\n}\n"],"names":["runUninstall","state"],"mappings":"AAkBA,eAAsBA,EAAaC,EAAsC,CACvE,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,cAEV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,eAAiB,KACvBA,EAAM,gBAAA,EAEN,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,mBAAoB,CAC7C,OAAQ,CAAC,UAAW,QAAS,WAAW,EACxC,MAAO,EAAA,CACR,EAEDA,EAAM,cAAgB,EACxB,MAAQ,CAGNA,EAAM,cAAgB,EACxB,QAAA,CACEA,EAAM,cAAgB,GACtBA,EAAM,gBAAA,CACR,EACF"}
@@ -6,7 +6,7 @@
6
6
  <title>Taskmaster Control</title>
7
7
  <meta name="color-scheme" content="dark light" />
8
8
  <link rel="icon" type="image/png" href="./favicon.png" />
9
- <script type="module" crossorigin src="./assets/index-BZ2Jt_PC.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-BTi4rBlY.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-BQEnHucA.css">
11
11
  </head>
12
12
  <body>
@@ -1,4 +1,6 @@
1
1
  import { resolveMainSessionKeyFromConfig } from "../../config/sessions.js";
2
+ import { uninstallCommand } from "../../commands/uninstall.js";
3
+ import { defaultRuntime } from "../../runtime.js";
2
4
  import { getLastHeartbeatEvent } from "../../infra/heartbeat-events.js";
3
5
  import { setHeartbeatsEnabled } from "../../infra/heartbeat-runner.js";
4
6
  import { enqueueSystemEvent, isSystemEventContextChanged } from "../../infra/system-events.js";
@@ -119,4 +121,35 @@ export const systemHandlers = {
119
121
  });
120
122
  respond(true, { ok: true }, undefined);
121
123
  },
124
+ "system.uninstall": async ({ params, respond, context }) => {
125
+ const purge = params.purge === true;
126
+ const validScopes = new Set(["service", "state", "workspace", "app"]);
127
+ const scopes = Array.isArray(params.scopes)
128
+ ? params.scopes.filter((s) => validScopes.has(s))
129
+ : ["service", "state", "workspace"];
130
+ const opts = {
131
+ service: scopes.includes("service"),
132
+ state: scopes.includes("state"),
133
+ workspace: scopes.includes("workspace"),
134
+ app: scopes.includes("app"),
135
+ purge,
136
+ yes: true,
137
+ nonInteractive: true,
138
+ };
139
+ const log = context.logGateway;
140
+ log.info(`system.uninstall: scopes=${scopes.join(",")} purge=${purge}`);
141
+ // Respond before running uninstall — the gateway will exit afterward
142
+ respond(true, { ok: true, scopes, purge }, undefined);
143
+ // Small delay to let the response reach the client
144
+ await new Promise((r) => setTimeout(r, 500));
145
+ try {
146
+ await uninstallCommand(defaultRuntime, opts);
147
+ }
148
+ catch (err) {
149
+ log.error(`system.uninstall failed: ${String(err)}`);
150
+ }
151
+ // Exit the gateway process — everything has been removed
152
+ log.info("system.uninstall complete, exiting gateway");
153
+ process.exit(0);
154
+ },
122
155
  };
@@ -175,7 +175,8 @@ function authorizeGatewayMethod(method, client) {
175
175
  method === "records.deleteField" ||
176
176
  method === "workspaces.create" ||
177
177
  method === "workspaces.remove" ||
178
- method === "memory.reindex") {
178
+ method === "memory.reindex" ||
179
+ method === "system.uninstall") {
179
180
  return errorShape(ErrorCodes.INVALID_REQUEST, "missing scope: operator.admin");
180
181
  }
181
182
  return errorShape(ErrorCodes.INVALID_REQUEST, "missing scope: operator.admin");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/taskmaster",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "description": "AI-powered business assistant for small businesses",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -958,6 +958,41 @@ If the Software row shows "Unknown", tap the **refresh** button (circular arrow)
958
958
 
959
959
  ---
960
960
 
961
+ ## Uninstalling Taskmaster
962
+
963
+ ### From the Control Panel
964
+
965
+ 1. Open the **Setup** page
966
+ 2. Scroll to the bottom of the dashboard
967
+ 3. Tap **Uninstall Taskmaster** (in red)
968
+ 4. Type **UNINSTALL** in the confirmation box
969
+ 5. Tap the **Uninstall** button
970
+
971
+ This stops the gateway, removes all configuration, workspace files, and attempts to remove the npm package. If the package could not be removed automatically (permissions), the page will show a command to run manually.
972
+
973
+ ### From the command line
974
+
975
+ To remove everything in one command:
976
+
977
+ ```bash
978
+ taskmaster uninstall --purge --yes
979
+ ```
980
+
981
+ This removes the gateway service, configuration (`~/.taskmaster`), workspace files (`~/taskmaster`), and the npm package itself. If the npm package removal fails due to permissions, re-run with:
982
+
983
+ ```bash
984
+ sudo npm uninstall -g @rubytech/taskmaster
985
+ ```
986
+
987
+ For partial removal (keeps the CLI installed), use individual flags:
988
+
989
+ - `--service` — remove the gateway service only
990
+ - `--state` — remove configuration and session data
991
+ - `--workspace` — remove workspace files
992
+ - `--all` — remove service + state + workspace (but not the CLI)
993
+
994
+ ---
995
+
961
996
  ## Getting Help
962
997
 
963
998
  - **Email:** taskmaster@rubytech.llc