@polderlabs/bizar-plugin 0.6.0 → 0.6.1

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/src/commands.ts CHANGED
@@ -70,6 +70,27 @@ export type SideEffect =
70
70
  args: unknown;
71
71
  };
72
72
 
73
+ /** Dialog component types that can be rendered in the dashboard. */
74
+ export type DialogComponent =
75
+ | "visual-plan"
76
+ | "plan-create"
77
+ | "plan-list"
78
+ | "help"
79
+ | "audit"
80
+ | "generic";
81
+
82
+ export interface DialogDescriptor {
83
+ id: string;
84
+ title: string;
85
+ command: string;
86
+ component: DialogComponent;
87
+ data?: Record<string, unknown>;
88
+ }
89
+
90
+ function generateId(): string {
91
+ return `dlg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
92
+ }
93
+
73
94
  export interface SlashCommandResult {
74
95
  handled: true;
75
96
  /** Text shown to the user / LLM. */
@@ -78,6 +99,8 @@ export interface SlashCommandResult {
78
99
  settingsPatch?: Partial<PlanSettings>;
79
100
  /** Optional side-effect to perform (file I/O lives in the hook, not here). */
80
101
  sideEffect?: SideEffect;
102
+ /** Optional dialog to open in the dashboard instead of showing text. */
103
+ dialog?: DialogDescriptor;
81
104
  }
82
105
 
83
106
  /**
@@ -285,43 +308,82 @@ export function parseSlashCommand(
285
308
 
286
309
  function handleVisualPlan(arg: string, ctx: ParseContext): SlashCommandResult {
287
310
  const lc = arg.toLowerCase();
311
+ const currentEnabled = ctx.currentSettings.visualPlanEnabled;
288
312
 
289
313
  if (lc === "") {
290
- // No argument — return current state
291
- const on = ctx.currentSettings.visualPlanEnabled ? "on" : "off";
314
+ // No argument — return current state as a dialog
292
315
  return {
293
316
  handled: true,
294
- response:
295
- `Visual plan mode is **${on}**.\n` +
296
- `Default template: ${ctx.currentSettings.defaultTemplate}\n` +
297
- (ctx.currentSettings.lastUsedSlug
298
- ? `Last used plan: ${ctx.currentSettings.lastUsedSlug}\n`
299
- : "") +
300
- `\nUsage: /visual-plan on | off`,
317
+ response: "",
318
+ dialog: {
319
+ id: generateId(),
320
+ title: "Visual Plan",
321
+ command: "/visual-plan",
322
+ component: "visual-plan",
323
+ data: {
324
+ enabled: currentEnabled,
325
+ previousEnabled: currentEnabled,
326
+ defaultTemplate: ctx.currentSettings.defaultTemplate,
327
+ lastUsedSlug: ctx.currentSettings.lastUsedSlug ?? null,
328
+ mode: "status",
329
+ },
330
+ },
301
331
  };
302
332
  }
303
333
 
304
334
  if (lc === "on" || lc === "true" || lc === "1" || lc === "enable") {
305
335
  return {
306
336
  handled: true,
307
- response: "Visual plan mode is now **on**. The agent will create a plan and wait for feedback on complex tasks.",
337
+ response: "",
308
338
  settingsPatch: { visualPlanEnabled: true },
339
+ dialog: {
340
+ id: generateId(),
341
+ title: "Visual Plan",
342
+ command: "/visual-plan on",
343
+ component: "visual-plan",
344
+ data: {
345
+ enabled: true,
346
+ previousEnabled: currentEnabled,
347
+ mode: "toggle",
348
+ },
349
+ },
309
350
  };
310
351
  }
311
352
 
312
353
  if (lc === "off" || lc === "false" || lc === "0" || lc === "disable") {
313
354
  return {
314
355
  handled: true,
315
- response: "Visual plan mode is now **off**.",
356
+ response: "",
316
357
  settingsPatch: { visualPlanEnabled: false },
358
+ dialog: {
359
+ id: generateId(),
360
+ title: "Visual Plan",
361
+ command: "/visual-plan off",
362
+ component: "visual-plan",
363
+ data: {
364
+ enabled: false,
365
+ previousEnabled: currentEnabled,
366
+ mode: "toggle",
367
+ },
368
+ },
317
369
  };
318
370
  }
319
371
 
320
372
  if (lc === "status" || lc === "state" || lc === "?") {
321
- const on = ctx.currentSettings.visualPlanEnabled ? "on" : "off";
322
373
  return {
323
374
  handled: true,
324
- response: `Visual plan mode: ${on}`,
375
+ response: "",
376
+ dialog: {
377
+ id: generateId(),
378
+ title: "Visual Plan",
379
+ command: "/visual-plan status",
380
+ component: "visual-plan",
381
+ data: {
382
+ enabled: currentEnabled,
383
+ previousEnabled: currentEnabled,
384
+ mode: "status",
385
+ },
386
+ },
325
387
  };
326
388
  }
327
389
 
@@ -382,21 +444,30 @@ function handlePlan(arg: string, ctx: ParseContext): SlashCommandResult {
382
444
  function helpPlan(): SlashCommandResult {
383
445
  return {
384
446
  handled: true,
385
- response:
386
- `Plan commands:\n` +
387
- ` /plan new <slug> [template] — Create a new plan\n` +
388
- ` /plan list — List all plans in the worktree\n` +
389
- ` /plan open <slug> — Return the URL for a plan\n` +
390
- ` /plan get <slug> — Fetch the full canvas\n` +
391
- ` /plan add <slug> --title T --type kind — Add an element to a plan\n` +
392
- ` /plan update <slug> <id> [--x N --y N …] — Patch an existing element\n` +
393
- ` /plan delete <slug> <id> — Remove an element\n` +
394
- ` /plan comment <slug> [id] "text" — Add a comment (canvas-pinned if no id)\n` +
395
- ` /plan comments <slug> [id] — Read comments on a plan\n` +
396
- ` /plan status <slug> <status> — Set the plan's status\n` +
397
- ` /plan wait <slug> [--timeout N] — Wait for feedback (deferred see note)\n` +
398
- `\nAvailable templates: ${KNOWN_TEMPLATES.join(", ")}\n` +
399
- `Available statuses: ${PLAN_STATUSES.join(", ")}`,
447
+ response: "",
448
+ dialog: {
449
+ id: generateId(),
450
+ title: "Plan Commands",
451
+ command: "/plan",
452
+ component: "help",
453
+ data: {
454
+ commands: [
455
+ { cmd: "/plan new <slug> [template]", desc: "Create a new plan" },
456
+ { cmd: "/plan list", desc: "List all plans in the worktree" },
457
+ { cmd: "/plan open <slug>", desc: "Open a plan in the viewer" },
458
+ { cmd: "/plan get <slug>", desc: "Fetch the full canvas" },
459
+ { cmd: "/plan add <slug> --title T --type kind", desc: "Add an element to a plan" },
460
+ { cmd: "/plan update <slug> <id> [--x N --y N …]", desc: "Patch an existing element" },
461
+ { cmd: "/plan delete <slug> <id>", desc: "Remove an element" },
462
+ { cmd: "/plan comment <slug> [id] \"text\"", desc: "Add a comment" },
463
+ { cmd: "/plan comments <slug> [id]", desc: "Read comments on a plan" },
464
+ { cmd: "/plan status <slug> <status>", desc: "Set the plan's status" },
465
+ { cmd: "/plan wait <slug> [--timeout N]", desc: "Wait for feedback (deferred)" },
466
+ ],
467
+ templates: KNOWN_TEMPLATES,
468
+ statuses: PLAN_STATUSES,
469
+ },
470
+ },
400
471
  };
401
472
  }
402
473
 
@@ -406,7 +477,18 @@ function handlePlanNew(args: string[], ctx: ParseContext): SlashCommandResult {
406
477
  if (args.length === 0 || args[0] === "") {
407
478
  return {
408
479
  handled: true,
409
- response: "Usage: /plan new <slug> [template]",
480
+ response: "",
481
+ dialog: {
482
+ id: generateId(),
483
+ title: "Create New Plan",
484
+ command: "/plan new",
485
+ component: "plan-create",
486
+ data: {
487
+ templates: [...KNOWN_TEMPLATES],
488
+ defaultTemplate: ctx.currentSettings.defaultTemplate,
489
+ suggestedSlug: "",
490
+ },
491
+ },
410
492
  };
411
493
  }
412
494
 
@@ -434,24 +516,27 @@ function handlePlanNew(args: string[], ctx: ParseContext): SlashCommandResult {
434
516
  template = candidate;
435
517
  }
436
518
 
437
- // The response surfaces the resolved template name (the user-supplied
438
- // argument, or the user's current default). The sideEffect carries
439
- // the explicit `null` so the executor knows to fall back to
440
- // `currentSettings.defaultTemplate` at write time.
441
519
  const resolvedTemplate = template ?? ctx.currentSettings.defaultTemplate;
442
520
 
443
521
  return {
444
522
  handled: true,
445
- response:
446
- `Plan "${titleCase(slug)}" (slug: ${slug}) will be created with the ` +
447
- `"${resolvedTemplate}" template.\n` +
448
- `After creation, use /plan open ${slug} to get the URL.`,
523
+ response: "",
449
524
  sideEffect: {
450
525
  kind: "create_plan",
451
526
  slug,
452
527
  template,
453
528
  },
454
529
  settingsPatch: { lastUsedSlug: slug },
530
+ dialog: {
531
+ id: generateId(),
532
+ title: "Plan Created",
533
+ command: `/plan new ${slug}`,
534
+ component: "generic",
535
+ data: {
536
+ message: `Plan "${titleCase(slug)}" created with the "${resolvedTemplate}" template.`,
537
+ detail: `Use /plan open ${slug} to open it.`,
538
+ },
539
+ },
455
540
  };
456
541
  }
457
542
 
@@ -459,19 +544,20 @@ function handlePlanNew(args: string[], ctx: ParseContext): SlashCommandResult {
459
544
 
460
545
  function handlePlanList(ctx: ParseContext): SlashCommandResult {
461
546
  const slugs = ctx.availablePlanSlugs ?? [];
462
- if (slugs.length === 0) {
463
- return {
464
- handled: true,
465
- response:
466
- "No plans found in this worktree. Use /plan new <slug> to create one.",
467
- sideEffect: { kind: "list_plans" },
468
- };
469
- }
470
- const lines = slugs.map((s) => ` - ${s}`);
471
547
  return {
472
548
  handled: true,
473
- response: `Plans in this worktree (${slugs.length}):\n${lines.join("\n")}`,
549
+ response: "",
474
550
  sideEffect: { kind: "list_plans" },
551
+ dialog: {
552
+ id: generateId(),
553
+ title: "Plans",
554
+ command: "/plan list",
555
+ component: "plan-list",
556
+ data: {
557
+ plans: slugs,
558
+ count: slugs.length,
559
+ },
560
+ },
475
561
  };
476
562
  }
477
563
 
@@ -498,16 +584,22 @@ function handlePlanOpen(args: string[], ctx: ParseContext): SlashCommandResult {
498
584
 
499
585
  return {
500
586
  handled: true,
501
- response:
502
- `Plan URL: ${url}\n` +
503
- `(v0.5.0 MVP — server startup is a future enhancement; the URL is ` +
504
- `informational. Use "bizar plan open ${slug}" in the terminal to ` +
505
- `start the local viewer.)`,
587
+ response: "",
506
588
  settingsPatch: { lastUsedSlug: slug },
507
589
  sideEffect: {
508
590
  kind: "open_plan_url",
509
591
  slug,
510
592
  },
593
+ dialog: {
594
+ id: generateId(),
595
+ title: "Opening Plan",
596
+ command: `/plan open ${slug}`,
597
+ component: "generic",
598
+ data: {
599
+ message: `Opening plan: ${slug}`,
600
+ url,
601
+ },
602
+ },
511
603
  };
512
604
  }
513
605
 
@@ -526,13 +618,22 @@ function handlePlanGet(args: string[]): SlashCommandResult {
526
618
  }
527
619
  return {
528
620
  handled: true,
529
- response: `Fetching canvas for plan "${slug}"…`,
621
+ response: "",
530
622
  sideEffect: {
531
623
  kind: "tool_invocation",
532
624
  toolName: "bizar_plan_action",
533
625
  args: { action: "get_canvas", planSlug: slug },
534
626
  },
535
627
  settingsPatch: { lastUsedSlug: slug },
628
+ dialog: {
629
+ id: generateId(),
630
+ title: "Plan Canvas",
631
+ command: `/plan get ${slug}`,
632
+ component: "generic",
633
+ data: {
634
+ message: `Fetching canvas for plan "${slug}"…`,
635
+ },
636
+ },
536
637
  };
537
638
  }
538
639
 
@@ -591,13 +692,22 @@ function handlePlanAdd(args: string[]): SlashCommandResult {
591
692
  }
592
693
  return {
593
694
  handled: true,
594
- response: `Adding element to plan "${slug}"…`,
695
+ response: "",
595
696
  sideEffect: {
596
697
  kind: "tool_invocation",
597
698
  toolName: "bizar_plan_action",
598
699
  args: { action: "add_element", planSlug: slug, element },
599
700
  },
600
701
  settingsPatch: { lastUsedSlug: slug },
702
+ dialog: {
703
+ id: generateId(),
704
+ title: "Element Added",
705
+ command: `/plan add ${slug}`,
706
+ component: "generic",
707
+ data: {
708
+ message: `Adding element to plan "${slug}"…`,
709
+ },
710
+ },
601
711
  };
602
712
  }
603
713
 
@@ -637,13 +747,22 @@ function handlePlanUpdate(args: string[]): SlashCommandResult {
637
747
  }
638
748
  return {
639
749
  handled: true,
640
- response: `Updating element ${elementId} in plan "${slug}"…`,
750
+ response: "",
641
751
  sideEffect: {
642
752
  kind: "tool_invocation",
643
753
  toolName: "bizar_plan_action",
644
754
  args: { action: "update_element", planSlug: slug, elementId, element },
645
755
  },
646
756
  settingsPatch: { lastUsedSlug: slug },
757
+ dialog: {
758
+ id: generateId(),
759
+ title: "Element Updated",
760
+ command: `/plan update ${slug}`,
761
+ component: "generic",
762
+ data: {
763
+ message: `Updating element ${elementId} in plan "${slug}"…`,
764
+ },
765
+ },
647
766
  };
648
767
  }
649
768
 
@@ -666,13 +785,22 @@ function handlePlanDelete(args: string[]): SlashCommandResult {
666
785
  }
667
786
  return {
668
787
  handled: true,
669
- response: `Deleting element ${elementId} from plan "${slug}"…`,
788
+ response: "",
670
789
  sideEffect: {
671
790
  kind: "tool_invocation",
672
791
  toolName: "bizar_plan_action",
673
792
  args: { action: "delete_element", planSlug: slug, elementId },
674
793
  },
675
794
  settingsPatch: { lastUsedSlug: slug },
795
+ dialog: {
796
+ id: generateId(),
797
+ title: "Element Deleted",
798
+ command: `/plan delete ${slug}`,
799
+ component: "generic",
800
+ data: {
801
+ message: `Deleting element ${elementId} from plan "${slug}"…`,
802
+ },
803
+ },
676
804
  };
677
805
  }
678
806
 
@@ -734,10 +862,7 @@ function commentSideEffect(
734
862
  ): SlashCommandResult {
735
863
  return {
736
864
  handled: true,
737
- response:
738
- elementId === null
739
- ? `Adding canvas-pinned comment to plan "${slug}"…`
740
- : `Adding comment to element ${elementId} on plan "${slug}"…`,
865
+ response: "",
741
866
  sideEffect: {
742
867
  kind: "tool_invocation",
743
868
  toolName: "bizar_plan_action",
@@ -752,6 +877,18 @@ function commentSideEffect(
752
877
  },
753
878
  },
754
879
  settingsPatch: { lastUsedSlug: slug },
880
+ dialog: {
881
+ id: generateId(),
882
+ title: "Comment Added",
883
+ command: `/plan comment ${slug}`,
884
+ component: "generic",
885
+ data: {
886
+ message:
887
+ elementId === null
888
+ ? `Adding canvas-pinned comment to plan "${slug}"…`
889
+ : `Adding comment to element ${elementId} on plan "${slug}"…`,
890
+ },
891
+ },
755
892
  };
756
893
  }
757
894
 
@@ -771,16 +908,25 @@ function handlePlanComments(args: string[]): SlashCommandResult {
771
908
  const elementId = args.length >= 2 ? args[1]! : undefined;
772
909
  return {
773
910
  handled: true,
774
- response:
775
- elementId === undefined
776
- ? `Reading comments on plan "${slug}"…`
777
- : `Reading comments on element ${elementId} of plan "${slug}"…`,
911
+ response: "",
778
912
  sideEffect: {
779
913
  kind: "tool_invocation",
780
914
  toolName: "bizar_get_plan_comments",
781
915
  args: elementId === undefined ? { planSlug: slug } : { planSlug: slug, elementId },
782
916
  },
783
917
  settingsPatch: { lastUsedSlug: slug },
918
+ dialog: {
919
+ id: generateId(),
920
+ title: "Comments",
921
+ command: `/plan comments ${slug}`,
922
+ component: "generic",
923
+ data: {
924
+ message:
925
+ elementId === undefined
926
+ ? `Reading comments on plan "${slug}"…`
927
+ : `Reading comments on element ${elementId} of plan "${slug}"…`,
928
+ },
929
+ },
784
930
  };
785
931
  }
786
932
 
@@ -809,13 +955,22 @@ function handlePlanStatus(args: string[]): SlashCommandResult {
809
955
  }
810
956
  return {
811
957
  handled: true,
812
- response: `Setting plan "${slug}" status to "${status}"…`,
958
+ response: "",
813
959
  sideEffect: {
814
960
  kind: "tool_invocation",
815
961
  toolName: "bizar_plan_action",
816
962
  args: { action: "set_status", planSlug: slug, status },
817
963
  },
818
964
  settingsPatch: { lastUsedSlug: slug },
965
+ dialog: {
966
+ id: generateId(),
967
+ title: "Status Updated",
968
+ command: `/plan status ${slug}`,
969
+ component: "generic",
970
+ data: {
971
+ message: `Setting plan "${slug}" status to "${status}"…`,
972
+ },
973
+ },
819
974
  };
820
975
  }
821
976
 
@@ -858,7 +1013,7 @@ function handlePlanWait(args: string[]): SlashCommandResult {
858
1013
  *
859
1014
  * Behavior:
860
1015
  * - `/bizar` (no args) — emits a `launch_dashboard` side-effect. The
861
- * executor spawns `bizar dashboard start` as a detached child
1016
+ * executor spawns `bizar dash start` as a detached child
862
1017
  * process, then the host surfaces the URL in the response.
863
1018
  * - `/bizar <args>` — passes the args to the menu command file. Today
864
1019
  * the menu routes intent (`/explain`, `/plan`, `/audit`, etc.); the
@@ -876,25 +1031,45 @@ function handleBizar(arg: string, ctx: ParseContext): SlashCommandResult {
876
1031
  const port = ctx.defaultPort ?? 4321;
877
1032
  return {
878
1033
  handled: true,
879
- response:
880
- `🪩 Bizar dashboard launching in the background.\n` +
881
- `Visit http://localhost:${port}/ once the server is ready.\n` +
882
- `(If the browser did not open automatically, click the URL above.)`,
1034
+ response: "",
883
1035
  sideEffect: {
884
1036
  kind: "launch_dashboard",
885
1037
  defaultPort: port,
886
1038
  },
1039
+ dialog: {
1040
+ id: generateId(),
1041
+ title: "Dashboard",
1042
+ command: "/bizar",
1043
+ component: "generic",
1044
+ data: {
1045
+ message: "Dashboard launching in the background…",
1046
+ url: `http://localhost:${port}/`,
1047
+ },
1048
+ },
887
1049
  };
888
1050
  }
889
1051
 
890
1052
  // With args, defer to the menu command file shipped with the CLI.
891
1053
  return {
892
1054
  handled: true,
893
- response:
894
- `🪩 Bizar routing your request: "${trimmed}"\n` +
895
- `The menu command file (config/commands/bizar.md) maps intents like\n` +
896
- `"explain X", "plan Y", "review PR", "audit", "learn", and "init"\n` +
897
- `to the right Bizar action. For the dashboard, use \`/bizar\` with no args.`,
1055
+ response: "",
1056
+ dialog: {
1057
+ id: generateId(),
1058
+ title: "Bizar Commands",
1059
+ command: `/bizar ${trimmed}`,
1060
+ component: "help",
1061
+ data: {
1062
+ commands: [
1063
+ { cmd: "/bizar", desc: "Launch the Bizar dashboard" },
1064
+ { cmd: "/bizar explain <question>", desc: "Read-only code Q&A" },
1065
+ { cmd: "/bizar plan <args>", desc: "Manage plans" },
1066
+ { cmd: "/bizar audit", desc: "Run security audit" },
1067
+ { cmd: "/bizar learn", desc: "Extract patterns from session" },
1068
+ { cmd: "/bizar init", desc: "Initialize .bizar/ in this project" },
1069
+ { cmd: "/bizar pr-review", desc: "PR review" },
1070
+ ],
1071
+ },
1072
+ },
898
1073
  };
899
1074
  }
900
1075
 
@@ -903,31 +1078,33 @@ function handleBizar(arg: string, ctx: ParseContext): SlashCommandResult {
903
1078
  function helpResult(): SlashCommandResult {
904
1079
  return {
905
1080
  handled: true,
906
- response:
907
- `Available commands:\n` +
908
- ` /visual-plan on | off — Toggle visual plan mode\n` +
909
- ` /visual-plan — Show current visual plan state\n` +
910
- `\n` +
911
- ` /plan new <slug> [template] — Create a new plan\n` +
912
- ` /plan list — List all plans in the worktree\n` +
913
- ` /plan open <slug> — Return the URL for a plan\n` +
914
- `\n` +
915
- ` /plan get <slug> Fetch the full canvas (via bizar_plan_action)\n` +
916
- ` /plan add <slug> --title T --type kind [--x N --y N …]\n` +
917
- ` — Add an element to a plan (via bizar_plan_action)\n` +
918
- ` /plan update <slug> <id> [--x N --y N --title T --content C …]\n` +
919
- ` — Patch an existing element (via bizar_plan_action)\n` +
920
- ` /plan delete <slug> <id> Remove an element (via bizar_plan_action)\n` +
921
- ` /plan comment <slug> [id] "text"\n` +
922
- ` — Add a comment (via bizar_plan_action)\n` +
923
- ` /plan comments <slug> [id] Read comments (via bizar_get_plan_comments)\n` +
924
- ` /plan status <slug> <status> Set the plan's status (via bizar_plan_action)\n` +
925
- ` /plan wait <slug> [--timeout N]\n` +
926
- ` — Wait for feedback (deferred see /plan wait)\n` +
927
- `\n` +
928
- ` /help | /commands Show this help\n` +
929
- `\n` +
930
- `Available templates: ${KNOWN_TEMPLATES.join(", ")}\n` +
931
- `Available statuses: ${PLAN_STATUSES.join(", ")}`,
1081
+ response: "",
1082
+ dialog: {
1083
+ id: generateId(),
1084
+ title: "Bizar Commands",
1085
+ command: "/help",
1086
+ component: "help",
1087
+ data: {
1088
+ commands: [
1089
+ { cmd: "/visual-plan [on|off|status]", desc: "Toggle or view visual plan mode" },
1090
+ { cmd: "/plan new <slug> [template]", desc: "Create a new plan" },
1091
+ { cmd: "/plan list", desc: "List all plans in the worktree" },
1092
+ { cmd: "/plan open <slug>", desc: "Open a plan in the viewer" },
1093
+ { cmd: "/plan get <slug>", desc: "Fetch the full canvas" },
1094
+ { cmd: "/plan add <slug> --title T --type kind", desc: "Add an element to a plan" },
1095
+ { cmd: "/plan update <slug> <id> [flags]", desc: "Patch an existing element" },
1096
+ { cmd: "/plan delete <slug> <id>", desc: "Remove an element" },
1097
+ { cmd: "/plan comment <slug> [id] \"text\"", desc: "Add a comment" },
1098
+ { cmd: "/plan comments <slug> [id]", desc: "Read comments on a plan" },
1099
+ { cmd: "/plan status <slug> <status>", desc: "Set the plan's status" },
1100
+ { cmd: "/plan wait <slug> [--timeout N]", desc: "Wait for feedback (deferred)" },
1101
+ { cmd: "/bizar", desc: "Launch the Bizar dashboard" },
1102
+ { cmd: "/bizar <args>", desc: "Route a request via the menu" },
1103
+ { cmd: "/help | /commands", desc: "Show this help" },
1104
+ ],
1105
+ templates: [...KNOWN_TEMPLATES],
1106
+ statuses: [...PLAN_STATUSES],
1107
+ },
1108
+ },
932
1109
  };
933
1110
  }