@lotics/cli 0.68.0 → 0.69.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.
package/README.md CHANGED
@@ -87,6 +87,7 @@ Workspaces live inside the active org. If the org has more than one, select befo
87
87
  lotics workspace # list workspaces in the active org (marks current)
88
88
  lotics workspace select wks_... # set the workspace for the active scope (pin or profile)
89
89
  lotics workspace create "Sales" # create a new workspace (admin only)
90
+ lotics workspace delete wks_... --yes # delete a workspace (admin only; soft delete, recoverable)
90
91
  ```
91
92
 
92
93
  Single-workspace organizations auto-select on first use. The selection is remembered per org, so switching back lands where you left off.
package/dist/args.d.ts CHANGED
@@ -30,6 +30,8 @@ export declare function parseArgs(argv: string[]): {
30
30
  message?: string;
31
31
  local: boolean;
32
32
  all: boolean;
33
+ /** `--yes` (alias `-y`): confirm a destructive command (e.g. `workspace delete`) non-interactively. */
34
+ yes: boolean;
33
35
  /** `--print-created` (alias `--report-effects`): print the honest post-run side-effect harvest. */
34
36
  printCreated: boolean;
35
37
  /** `--cleanup`: also delete the harvested created records (records only). */
package/dist/args.js CHANGED
@@ -25,6 +25,7 @@ export function parseArgs(argv) {
25
25
  message: undefined,
26
26
  local: false,
27
27
  all: false,
28
+ yes: false,
28
29
  printCreated: false,
29
30
  cleanup: false,
30
31
  version: false,
@@ -80,6 +81,10 @@ export function parseArgs(argv) {
80
81
  case "--all":
81
82
  flags.all = true;
82
83
  break;
84
+ case "--yes":
85
+ case "-y":
86
+ flags.yes = true;
87
+ break;
83
88
  case "--print-created":
84
89
  case "--report-effects":
85
90
  flags.printCreated = true;
package/dist/args.test.js CHANGED
@@ -63,6 +63,14 @@ describe("parseArgs", () => {
63
63
  expect(parseArgs(["app", "workflow", "run", "wf"]).flags.cleanup).toBe(false);
64
64
  expect(parseArgs(["app", "workflow", "run", "wf"]).flags.printCreated).toBe(false);
65
65
  });
66
+ it("parses --yes and -y as the same boolean confirmation flag (default false)", () => {
67
+ expect(parseArgs(["workspace", "delete", "wsp_1", "--yes"]).flags.yes).toBe(true);
68
+ expect(parseArgs(["workspace", "delete", "wsp_1", "-y"]).flags.yes).toBe(true);
69
+ const r = parseArgs(["workspace", "delete", "wsp_1"]);
70
+ expect(r.flags.yes).toBe(false);
71
+ // The boolean flag does not consume the id positional.
72
+ expect(parseArgs(["workspace", "delete", "wsp_1", "--yes"]).toolArgs).toBe("wsp_1");
73
+ });
66
74
  it("treats `org use <name>` as command / subcommand / positional", () => {
67
75
  const r = parseArgs(["org", "use", "Acme Corp"]);
68
76
  expect(r.command).toBe("org");
package/dist/cli.js CHANGED
@@ -60,6 +60,7 @@ COMMANDS
60
60
  lotics workspace List workspaces in the active org (marks current)
61
61
  lotics workspace select <id> Switch to a different workspace
62
62
  lotics workspace create <name> Create a new workspace (admin only)
63
+ lotics workspace delete <id> --yes Delete a workspace (admin only; soft delete, recoverable)
63
64
  lotics tools List all available tools
64
65
  lotics tools <name> Show tool description and input schema
65
66
  lotics run <tool> '<json>' Execute a tool
@@ -688,10 +689,41 @@ async function main() {
688
689
  }
689
690
  return;
690
691
  }
692
+ if (subcommand === "delete") {
693
+ const targetId = toolArgs;
694
+ if (!targetId) {
695
+ console.error('Usage: lotics workspace delete <workspace_id> --yes');
696
+ process.exit(1);
697
+ }
698
+ const target = workspaces.find((ws) => ws.id === targetId);
699
+ if (!target) {
700
+ console.error(`Workspace not found: ${targetId}\n\nAvailable workspaces:`);
701
+ printWorkspaceList(workspaces, currentWorkspaceId);
702
+ process.exit(1);
703
+ }
704
+ // Destructive + irreversible-looking to the user — require an explicit
705
+ // confirmation (this CLI is used non-interactively by agents and scripts).
706
+ if (!flags.yes) {
707
+ console.error(`This deletes workspace "${target.name}" (${target.id}) — every table, app, record, and template inside it becomes inaccessible (soft delete: retained and recoverable by an admin).`);
708
+ console.error(`Re-run with --yes to confirm: lotics workspace delete ${target.id} --yes`);
709
+ process.exit(1);
710
+ }
711
+ const deleted = await client.deleteWorkspace(target.id);
712
+ if (flags.json) {
713
+ console.log(JSON.stringify(deleted, null, 2));
714
+ }
715
+ else {
716
+ console.error(`Deleted workspace: ${target.name} (${target.id})`);
717
+ if (currentWorkspaceId === target.id) {
718
+ console.error('This was your selected workspace — select another with "lotics workspace select <id>".');
719
+ }
720
+ }
721
+ return;
722
+ }
691
723
  // Default: list workspaces
692
724
  if (subcommand && subcommand !== "list") {
693
725
  console.error(`Unknown workspace subcommand: ${subcommand}`);
694
- console.error('Usage: lotics workspace [list | select <id> | create <name>]');
726
+ console.error('Usage: lotics workspace [list | select <id> | create <name> | delete <id> --yes]');
695
727
  process.exit(1);
696
728
  }
697
729
  if (flags.json) {
package/dist/client.d.ts CHANGED
@@ -93,6 +93,10 @@ export declare class LoticsClient {
93
93
  name: string;
94
94
  timezone?: string;
95
95
  }): Promise<WorkspaceInfo>;
96
+ deleteWorkspace(id: string): Promise<{
97
+ id: string;
98
+ deleted: boolean;
99
+ }>;
96
100
  login(): Promise<{
97
101
  email: string;
98
102
  }>;
package/dist/client.js CHANGED
@@ -142,6 +142,9 @@ export class LoticsClient {
142
142
  async createWorkspace(body) {
143
143
  return this.request("POST", "/v1/workspaces", body);
144
144
  }
145
+ async deleteWorkspace(id) {
146
+ return this.request("DELETE", `/v1/workspaces/${encodeURIComponent(id)}`);
147
+ }
145
148
  async login() {
146
149
  return this.request("POST", "/v1/cli/login");
147
150
  }
package/dist/src/cli.js CHANGED
@@ -29704,6 +29704,9 @@ var LoticsClient = class {
29704
29704
  async createWorkspace(body) {
29705
29705
  return this.request("POST", "/v1/workspaces", body);
29706
29706
  }
29707
+ async deleteWorkspace(id) {
29708
+ return this.request("DELETE", `/v1/workspaces/${encodeURIComponent(id)}`);
29709
+ }
29707
29710
  async login() {
29708
29711
  return this.request("POST", "/v1/cli/login");
29709
29712
  }
@@ -30638,10 +30641,18 @@ export default defineConfig({
30638
30641
  // the hooks dispatcher the instant a hook (useAgentRun / useQuery)
30639
30642
  // runs in a rendered App tree.
30640
30643
  "@lotics/app-sdk",
30644
+ // The /router subpath is a SEPARATE optimizer entry \u2014 without it,
30645
+ // AppRouter's BrowserRouter bundles apart from the app's
30646
+ // react-router hooks and the Router context never matches
30647
+ // ("useNavigate() may be used only in the context of a <Router>").
30648
+ "@lotics/app-sdk/router",
30641
30649
  // react-router-dom (App's router) also ships compiled dist JS \u2014 pin it
30642
30650
  // into the shared chunk so its hooks don't split the react instance
30643
30651
  // ("Invalid hook call") when a test renders the routed App tree.
30644
30652
  "react-router-dom",
30653
+ // v7: react-router-dom is a thin wrapper \u2014 the actual context
30654
+ // lives in react-router; both must ride the shared chunk.
30655
+ "react-router",
30645
30656
  ],
30646
30657
  esbuildOptions: {
30647
30658
  resolveExtensions: [".web.tsx", ".web.ts", ".web.js", ".tsx", ".ts", ".jsx", ".js", ".json"],
@@ -33164,6 +33175,7 @@ function parseArgs(argv) {
33164
33175
  message: void 0,
33165
33176
  local: false,
33166
33177
  all: false,
33178
+ yes: false,
33167
33179
  printCreated: false,
33168
33180
  cleanup: false,
33169
33181
  version: false,
@@ -33219,6 +33231,10 @@ function parseArgs(argv) {
33219
33231
  case "--all":
33220
33232
  flags.all = true;
33221
33233
  break;
33234
+ case "--yes":
33235
+ case "-y":
33236
+ flags.yes = true;
33237
+ break;
33222
33238
  case "--print-created":
33223
33239
  case "--report-effects":
33224
33240
  flags.printCreated = true;
@@ -49681,6 +49697,7 @@ COMMANDS
49681
49697
  lotics workspace List workspaces in the active org (marks current)
49682
49698
  lotics workspace select <id> Switch to a different workspace
49683
49699
  lotics workspace create <name> Create a new workspace (admin only)
49700
+ lotics workspace delete <id> --yes Delete a workspace (admin only; soft delete, recoverable)
49684
49701
  lotics tools List all available tools
49685
49702
  lotics tools <name> Show tool description and input schema
49686
49703
  lotics run <tool> '<json>' Execute a tool
@@ -50261,9 +50278,39 @@ Available workspaces:`);
50261
50278
  }
50262
50279
  return;
50263
50280
  }
50281
+ if (subcommand === "delete") {
50282
+ const targetId = toolArgs;
50283
+ if (!targetId) {
50284
+ console.error("Usage: lotics workspace delete <workspace_id> --yes");
50285
+ process.exit(1);
50286
+ }
50287
+ const target = workspaces.find((ws) => ws.id === targetId);
50288
+ if (!target) {
50289
+ console.error(`Workspace not found: ${targetId}
50290
+
50291
+ Available workspaces:`);
50292
+ printWorkspaceList(workspaces, currentWorkspaceId);
50293
+ process.exit(1);
50294
+ }
50295
+ if (!flags.yes) {
50296
+ console.error(`This deletes workspace "${target.name}" (${target.id}) \u2014 every table, app, record, and template inside it becomes inaccessible (soft delete: retained and recoverable by an admin).`);
50297
+ console.error(`Re-run with --yes to confirm: lotics workspace delete ${target.id} --yes`);
50298
+ process.exit(1);
50299
+ }
50300
+ const deleted = await client.deleteWorkspace(target.id);
50301
+ if (flags.json) {
50302
+ console.log(JSON.stringify(deleted, null, 2));
50303
+ } else {
50304
+ console.error(`Deleted workspace: ${target.name} (${target.id})`);
50305
+ if (currentWorkspaceId === target.id) {
50306
+ console.error('This was your selected workspace \u2014 select another with "lotics workspace select <id>".');
50307
+ }
50308
+ }
50309
+ return;
50310
+ }
50264
50311
  if (subcommand && subcommand !== "list") {
50265
50312
  console.error(`Unknown workspace subcommand: ${subcommand}`);
50266
- console.error("Usage: lotics workspace [list | select <id> | create <name>]");
50313
+ console.error("Usage: lotics workspace [list | select <id> | create <name> | delete <id> --yes]");
50267
50314
  process.exit(1);
50268
50315
  }
50269
50316
  if (flags.json) {
@@ -316,10 +316,18 @@ export default defineConfig({
316
316
  // the hooks dispatcher the instant a hook (useAgentRun / useQuery)
317
317
  // runs in a rendered App tree.
318
318
  "@lotics/app-sdk",
319
+ // The /router subpath is a SEPARATE optimizer entry — without it,
320
+ // AppRouter's BrowserRouter bundles apart from the app's
321
+ // react-router hooks and the Router context never matches
322
+ // ("useNavigate() may be used only in the context of a <Router>").
323
+ "@lotics/app-sdk/router",
319
324
  // react-router-dom (App's router) also ships compiled dist JS — pin it
320
325
  // into the shared chunk so its hooks don't split the react instance
321
326
  // ("Invalid hook call") when a test renders the routed App tree.
322
327
  "react-router-dom",
328
+ // v7: react-router-dom is a thin wrapper — the actual context
329
+ // lives in react-router; both must ride the shared chunk.
330
+ "react-router",
323
331
  ],
324
332
  esbuildOptions: {
325
333
  resolveExtensions: [".web.tsx", ".web.ts", ".web.js", ".tsx", ".ts", ".jsx", ".js", ".json"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.68.0",
3
+ "version": "0.69.0",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {