@go-labs-sg/bb 2.33.2 → 2.34.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
@@ -12,6 +12,16 @@ For AI agents using this CLI: do not execute mutations until the user explicitly
12
12
 
13
13
  **Registry:** [`@go-labs-sg/bb`](https://www.npmjs.com/package/@go-labs-sg/bb)
14
14
 
15
+ ## Company discovery and reuse
16
+
17
+ `bb company search --query "a star" [--page 2]` searches stored BB companies and QuickBooks company customers, including inactive records. Results identify `bb`, `qbo`, or `both`; punctuation/spacing normalization is for suggestions only. Search does not write to either system.
18
+
19
+ After reviewing a result, `bb company use --companyId <bbId>` reuses BB and resolves its QBO customer. `bb company use --quickbooksId <qboId>` imports the existing QBO name/website when BB is missing. Supply both IDs to explicitly connect two unlinked records whose names differ; existing company details are preserved. If QBO has no website, add `--website <url>` for the BB import only.
20
+
21
+ The shared API rechecks existing records at submission. Canonical matches reuse records; fuzzy matches require an explicit choice or `--confirmDistinct true` to confirm a separate legal entity. Inactive companies and conflicting links require review, never implicit reactivation. QBO project/sub-customers are not company-import candidates. Provider failures are not treated as missing records.
22
+
23
+ `bb company use` and `bb company create` are state-changing, potentially external-writing commands. In non-interactive mode their existing permission gates require `--allow-state-change --allow-external-write`. Deploy the backend before publishing this CLI change. See [company discovery details](../api/docs/company-discovery.md) for limits and retry behaviour.
24
+
15
25
  ## Shared catalogue editing
16
26
 
17
27
  All active authenticated users can edit suppliers, inventory items and item categories. Normal-user supplier updates submit a revision for approval in the shared API; item/category edits apply immediately. Lead/Admin supplier edits bypass human review. `bb supplier update` returns the server-owned approval/synchronization result without issuing another approval request. New supplier usage stays on hold during review and linked QuickBooks synchronization; existing usage continues with the last approved details until the edit is approved. Creator identity and delete/archive permissions are unchanged.
@@ -4790,10 +4790,134 @@
4790
4790
  "effects": [],
4791
4791
  "legacyTarget": "get-company"
4792
4792
  },
4793
+ {
4794
+ "path": ["company", "search"],
4795
+ "legacyAliases": ["search-existing-companies", "search_existing_companies"],
4796
+ "summary": "Search BB and QuickBooks companies without writes. --query <name> [--page <number>].",
4797
+ "globalOptions": [
4798
+ {
4799
+ "name": "--help",
4800
+ "description": "Show help for this command."
4801
+ },
4802
+ {
4803
+ "name": "--quiet",
4804
+ "description": "Suppress non-error diagnostics."
4805
+ },
4806
+ {
4807
+ "name": "--debug",
4808
+ "description": "Emit sanitized diagnostic traces."
4809
+ },
4810
+ {
4811
+ "name": "--api-url",
4812
+ "description": "Override the Budget Builder API base URL."
4813
+ },
4814
+ {
4815
+ "name": "--no-browser",
4816
+ "description": "Print the authorization URL without opening a browser."
4817
+ },
4818
+ {
4819
+ "name": "--allow-state-change",
4820
+ "description": "Allow a Budget Builder state change in non-interactive use."
4821
+ },
4822
+ {
4823
+ "name": "--allow-email",
4824
+ "description": "Allow sending email in non-interactive use."
4825
+ },
4826
+ {
4827
+ "name": "--allow-external-write",
4828
+ "description": "Allow writes to external systems in non-interactive use."
4829
+ },
4830
+ {
4831
+ "name": "--allow-delete",
4832
+ "description": "Allow deleting data in non-interactive use."
4833
+ },
4834
+ {
4835
+ "name": "--allow-financial-write",
4836
+ "description": "Allow financial-record changes in non-interactive use."
4837
+ },
4838
+ {
4839
+ "name": "--query",
4840
+ "description": "Company name to search in BB and QuickBooks."
4841
+ },
4842
+ {
4843
+ "name": "--page",
4844
+ "description": "Results page (eight companies per page)."
4845
+ }
4846
+ ],
4847
+ "argumentMode": "legacy-passthrough",
4848
+ "effects": [],
4849
+ "legacyTarget": "search-existing-companies"
4850
+ },
4851
+ {
4852
+ "path": ["company", "use"],
4853
+ "legacyAliases": ["use-existing-company", "use_existing_company"],
4854
+ "summary": "Reuse a company in BB and QuickBooks, creating only its missing counterpart. Supply --companyId <bbId> and/or --quickbooksId <qboId>; both explicitly connect records with different names. --website <url> fills a missing QBO import website only. --confirmDistinct true confirms no similar record represents this entity.",
4855
+ "globalOptions": [
4856
+ {
4857
+ "name": "--help",
4858
+ "description": "Show help for this command."
4859
+ },
4860
+ {
4861
+ "name": "--quiet",
4862
+ "description": "Suppress non-error diagnostics."
4863
+ },
4864
+ {
4865
+ "name": "--debug",
4866
+ "description": "Emit sanitized diagnostic traces."
4867
+ },
4868
+ {
4869
+ "name": "--api-url",
4870
+ "description": "Override the Budget Builder API base URL."
4871
+ },
4872
+ {
4873
+ "name": "--no-browser",
4874
+ "description": "Print the authorization URL without opening a browser."
4875
+ },
4876
+ {
4877
+ "name": "--allow-state-change",
4878
+ "description": "Allow a Budget Builder state change in non-interactive use."
4879
+ },
4880
+ {
4881
+ "name": "--allow-email",
4882
+ "description": "Allow sending email in non-interactive use."
4883
+ },
4884
+ {
4885
+ "name": "--allow-external-write",
4886
+ "description": "Allow writes to external systems in non-interactive use."
4887
+ },
4888
+ {
4889
+ "name": "--allow-delete",
4890
+ "description": "Allow deleting data in non-interactive use."
4891
+ },
4892
+ {
4893
+ "name": "--allow-financial-write",
4894
+ "description": "Allow financial-record changes in non-interactive use."
4895
+ },
4896
+ {
4897
+ "name": "--companyId",
4898
+ "description": "Existing BB company ID; combine with quickbooksId to explicitly connect both records."
4899
+ },
4900
+ {
4901
+ "name": "--quickbooksId",
4902
+ "description": "Existing QBO customer ID; alone imports or reuses its BB company."
4903
+ },
4904
+ {
4905
+ "name": "--website",
4906
+ "description": "Website only when missing from a QBO-only import."
4907
+ },
4908
+ {
4909
+ "name": "--confirmDistinct",
4910
+ "description": "Set true only when similar records do not represent this legal entity."
4911
+ }
4912
+ ],
4913
+ "argumentMode": "legacy-passthrough",
4914
+ "effects": ["state-change", "external-write"],
4915
+ "legacyTarget": "use-existing-company"
4916
+ },
4793
4917
  {
4794
4918
  "path": ["company", "create"],
4795
4919
  "legacyAliases": ["create-company", "create_company"],
4796
- "summary": "Create Company.",
4920
+ "summary": "Create or reuse a company in BB and QuickBooks. --name <name> --website <url>. Similar names require --confirmDistinct true; inactive companies are never reactivated.",
4797
4921
  "globalOptions": [
4798
4922
  {
4799
4923
  "name": "--help",
@@ -4834,6 +4958,10 @@
4834
4958
  {
4835
4959
  "name": "--allow-financial-write",
4836
4960
  "description": "Allow financial-record changes in non-interactive use."
4961
+ },
4962
+ {
4963
+ "name": "--confirmDistinct",
4964
+ "description": "Set true to confirm a separate legal entity despite similar names."
4837
4965
  }
4838
4966
  ],
4839
4967
  "argumentMode": "legacy-passthrough",
@@ -769,9 +769,25 @@ Legacy aliases: `get-company`, `get_company`.
769
769
 
770
770
  Effects: none.
771
771
 
772
+ ## `bb company search`
773
+
774
+ Search BB and QuickBooks companies without writes. --query <name> [--page <number>].
775
+
776
+ Legacy aliases: `search-existing-companies`, `search_existing_companies`.
777
+
778
+ Effects: none.
779
+
780
+ ## `bb company use`
781
+
782
+ Reuse a company in BB and QuickBooks, creating only its missing counterpart. Supply --companyId <bbId> and/or --quickbooksId <qboId>; both explicitly connect records with different names. --website <url> fills a missing QBO import website only. --confirmDistinct true confirms no similar record represents this entity.
783
+
784
+ Legacy aliases: `use-existing-company`, `use_existing_company`.
785
+
786
+ Effects: state-change, external-write.
787
+
772
788
  ## `bb company create`
773
789
 
774
- Create Company.
790
+ Create or reuse a company in BB and QuickBooks. --name <name> --website <url>. Similar names require --confirmDistinct true; inactive companies are never reactivated.
775
791
 
776
792
  Legacy aliases: `create-company`, `create_company`.
777
793
 
package/dist/index.js CHANGED
@@ -22818,6 +22818,12 @@ async function createCompany(opts) {
22818
22818
  const result = await api2.company.createCompany.mutate(opts);
22819
22819
  out(result);
22820
22820
  }
22821
+ var searchExistingCompanies = async (query, page = 1) => {
22822
+ out(await api2.company.searchExistingCompanies.query({ query, page }));
22823
+ };
22824
+ var reuseExistingCompany = async (input2) => {
22825
+ out(await api2.company.useExistingCompany.mutate(input2));
22826
+ };
22821
22827
  async function listProjects(opts) {
22822
22828
  const result = await api2.project.getAllProjects.query({
22823
22829
  companyId: opts.companyId,
@@ -23336,6 +23342,7 @@ var mutationPrefixes = [
23336
23342
  "submit-",
23337
23343
  "sync-",
23338
23344
  "update-",
23345
+ "use-existing-",
23339
23346
  "upload-",
23340
23347
  "void-"
23341
23348
  ];
@@ -23366,6 +23373,7 @@ var externalWriteTargets = new Set([
23366
23373
  "complete-project",
23367
23374
  "create-bill",
23368
23375
  "create-company",
23376
+ "use-existing-company",
23369
23377
  "create-estimate",
23370
23378
  "create-placeholder-bill",
23371
23379
  "create-customer-invoice",
@@ -23463,6 +23471,12 @@ var effectsFor = (legacyTarget) => {
23463
23471
  };
23464
23472
  var titleCase = (value) => value.split("-").map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`).join(" ");
23465
23473
  var summaryFor = (legacyTarget) => {
23474
+ if (legacyTarget === "search-existing-companies")
23475
+ return "Search BB and QuickBooks companies without writes. --query <name> [--page <number>].";
23476
+ if (legacyTarget === "use-existing-company")
23477
+ return "Reuse a company in BB and QuickBooks, creating only its missing counterpart. Supply --companyId <bbId> and/or --quickbooksId <qboId>; both explicitly connect records with different names. --website <url> fills a missing QBO import website only. --confirmDistinct true confirms no similar record represents this entity.";
23478
+ if (legacyTarget === "create-company")
23479
+ return "Create or reuse a company in BB and QuickBooks. --name <name> --website <url>. Similar names require --confirmDistinct true; inactive companies are never reactivated.";
23466
23480
  if (legacyTarget === "preview-qbo-customer-invoice") {
23467
23481
  return "Preview an existing QuickBooks invoice for a BB budget using read-only QBO access. Arguments: <budgetId> <qboInvoiceId>.";
23468
23482
  }
@@ -23726,7 +23740,40 @@ var registry2 = [
23726
23740
  legacyCommand("get-supplier-details", ["supplier", "detail", "get"]),
23727
23741
  legacyCommand("list-companies", ["company", "list"]),
23728
23742
  legacyCommand("get-company", ["company", "get"]),
23729
- legacyCommand("create-company", ["company", "create"]),
23743
+ legacyCommand("search-existing-companies", ["company", "search"], [], [
23744
+ {
23745
+ name: "--query",
23746
+ description: "Company name to search in BB and QuickBooks."
23747
+ },
23748
+ {
23749
+ name: "--page",
23750
+ description: "Results page (eight companies per page)."
23751
+ }
23752
+ ]),
23753
+ legacyCommand("use-existing-company", ["company", "use"], [], [
23754
+ {
23755
+ name: "--companyId",
23756
+ description: "Existing BB company ID; combine with quickbooksId to explicitly connect both records."
23757
+ },
23758
+ {
23759
+ name: "--quickbooksId",
23760
+ description: "Existing QBO customer ID; alone imports or reuses its BB company."
23761
+ },
23762
+ {
23763
+ name: "--website",
23764
+ description: "Website only when missing from a QBO-only import."
23765
+ },
23766
+ {
23767
+ name: "--confirmDistinct",
23768
+ description: "Set true only when similar records do not represent this legal entity."
23769
+ }
23770
+ ]),
23771
+ legacyCommand("create-company", ["company", "create"], [], [
23772
+ {
23773
+ name: "--confirmDistinct",
23774
+ description: "Set true to confirm a separate legal entity despite similar names."
23775
+ }
23776
+ ]),
23730
23777
  legacyCommand("update-company", ["company", "update"]),
23731
23778
  legacyCommand("delete-company", ["company", "delete"]),
23732
23779
  legacyCommand("list-projects", ["project", "list"]),
@@ -24263,7 +24310,12 @@ Companies & projects
24263
24310
  list-companies [--name] [--createdBy] [--active true|false] [--page] [--perPage]
24264
24311
  Omit --active to include both active and inactive companies.
24265
24312
  get-company <id>
24266
- create-company --name --website <url>
24313
+ search-existing-companies --query <name> [--page] (BB + QuickBooks, read-only)
24314
+ use-existing-company --companyId <bbId> and/or --quickbooksId <qboId> [--website <url>] [--confirmDistinct true]
24315
+ Supply both IDs to explicitly connect existing records with different names.
24316
+ Reuses both records, creating only the missing counterpart. Website is needed only for a QBO import without one.
24317
+ create-company --name --website <url> [--confirmDistinct true]
24318
+ Exact existing companies are reused. Similar names require explicit separate-entity confirmation.
24267
24319
  update-company --payload '<json>' (company.updateCompany; must include id, name, website)
24268
24320
  delete-company <id>
24269
24321
  list-projects [--companyId] [--name] [--status] [--active true|false] [--page] [--perPage]
@@ -25651,7 +25703,39 @@ Waiting for approval\u2026
25651
25703
  if (!name || !website) {
25652
25704
  throw new Error("create-company requires --name and --website <url>");
25653
25705
  }
25654
- await createCompany({ name, website });
25706
+ await createCompany({
25707
+ name,
25708
+ website,
25709
+ confirmDistinct: parseOptionalBoolFlag(flags, "confirmDistinct")
25710
+ });
25711
+ break;
25712
+ }
25713
+ case "search-existing-companies": {
25714
+ const query = getFlag(flags, "query");
25715
+ if (!query)
25716
+ throw new Error("search-existing-companies requires --query <name>");
25717
+ await searchExistingCompanies(query, parsePositiveIntFlag(getFlag(flags, "page"), "--page"));
25718
+ break;
25719
+ }
25720
+ case "use-existing-company": {
25721
+ const companyId = getFlag(flags, "companyId");
25722
+ const quickbooksId = getFlag(flags, "quickbooksId");
25723
+ if (!companyId && !quickbooksId)
25724
+ throw new Error("Supply --companyId and/or --quickbooksId");
25725
+ if (companyId)
25726
+ await reuseExistingCompany({
25727
+ source: "bb",
25728
+ companyId,
25729
+ quickbooksId,
25730
+ confirmDistinct: parseOptionalBoolFlag(flags, "confirmDistinct")
25731
+ });
25732
+ else if (quickbooksId)
25733
+ await reuseExistingCompany({
25734
+ source: "qbo",
25735
+ quickbooksId,
25736
+ website: getFlag(flags, "website"),
25737
+ confirmDistinct: parseOptionalBoolFlag(flags, "confirmDistinct")
25738
+ });
25655
25739
  break;
25656
25740
  }
25657
25741
  case "update-company": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/bb",
3
- "version": "2.33.2",
3
+ "version": "2.34.0",
4
4
  "description": "Budget Builder CLI for AI agents — manage budgets, bills, claims, quotations, and customer invoices with explicit workflow previews for sensitive changes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",