@rubytech/create-maxy 1.0.499 → 1.0.500

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.
Files changed (109) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  3. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/PLUGIN.md +36 -8
  4. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js +229 -153
  5. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js.map +1 -1
  6. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts +19 -1
  7. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts.map +1 -1
  8. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js +99 -3
  9. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js.map +1 -1
  10. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts +10 -0
  11. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts.map +1 -0
  12. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js +24 -0
  13. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js.map +1 -0
  14. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts +16 -0
  15. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts.map +1 -0
  16. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js +35 -0
  17. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js.map +1 -0
  18. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js +1 -1
  19. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js.map +1 -1
  20. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts +13 -0
  21. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts.map +1 -0
  22. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js +41 -0
  23. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js.map +1 -0
  24. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts +9 -0
  25. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts.map +1 -0
  26. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js +16 -0
  27. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js.map +1 -0
  28. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts +15 -0
  29. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts.map +1 -0
  30. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js +11 -0
  31. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js.map +1 -0
  32. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts +10 -0
  33. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts.map +1 -0
  34. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js +39 -0
  35. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js.map +1 -0
  36. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts +9 -0
  37. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts.map +1 -0
  38. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js +33 -0
  39. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js.map +1 -0
  40. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts +18 -0
  41. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts.map +1 -0
  42. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js +59 -0
  43. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js.map +1 -0
  44. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts +10 -0
  45. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts.map +1 -0
  46. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js +39 -0
  47. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js.map +1 -0
  48. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts +12 -0
  49. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts.map +1 -0
  50. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js +28 -0
  51. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js.map +1 -0
  52. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts +15 -0
  53. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts.map +1 -0
  54. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js +11 -0
  55. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js.map +1 -0
  56. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts +16 -0
  57. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts.map +1 -0
  58. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js +39 -0
  59. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js.map +1 -0
  60. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts +13 -0
  61. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts.map +1 -0
  62. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js +49 -0
  63. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js.map +1 -0
  64. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts +7 -0
  65. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts.map +1 -0
  66. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js +15 -0
  67. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js.map +1 -0
  68. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts +14 -0
  69. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts.map +1 -0
  70. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js +11 -0
  71. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js.map +1 -0
  72. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts +9 -0
  73. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts.map +1 -0
  74. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js +40 -0
  75. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js.map +1 -0
  76. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts +13 -0
  77. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts.map +1 -0
  78. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js +34 -0
  79. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js.map +1 -0
  80. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts +14 -0
  81. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts.map +1 -0
  82. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js +18 -0
  83. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js.map +1 -0
  84. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/index.ts +335 -158
  85. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/lib/loop-api.ts +140 -3
  86. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/customer-preferences.ts +60 -0
  87. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/feedback.ts +80 -0
  88. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/key-register.ts +1 -1
  89. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-enquiry.ts +105 -0
  90. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match-batch.ts +48 -0
  91. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match-request.ts +37 -0
  92. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match.ts +78 -0
  93. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-detail.ts +63 -0
  94. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-search.ts +93 -0
  95. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-detail.ts +70 -0
  96. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-listed.ts +67 -0
  97. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-request.ts +37 -0
  98. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-search.ts +80 -0
  99. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/supplier.ts +120 -0
  100. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/team-availability.ts +42 -0
  101. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-create.ts +36 -0
  102. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-detail.ts +70 -0
  103. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-search.ts +74 -0
  104. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-update.ts +48 -0
  105. package/payload/server/server.js +89 -2
  106. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/feedback-list.ts +0 -54
  107. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-list.ts +0 -52
  108. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/properties-list.ts +0 -52
  109. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewings-list.ts +0 -62
@@ -0,0 +1,48 @@
1
+ import { loopPost, withTeamKey } from "../lib/loop-api.js";
2
+
3
+ type Department = "sales" | "lettings";
4
+
5
+ // Feedback parties map to swagger endpoints:
6
+ // sales: buyer-feedback, seller-feedback
7
+ // lettings: renter-feedback, landlord-feedback
8
+ type FeedbackParty = "buyer" | "seller" | "renter" | "landlord";
9
+ type Action = "note" | "feedback";
10
+
11
+ interface LoopBooleanResponse {
12
+ success?: boolean;
13
+ [key: string]: unknown;
14
+ }
15
+
16
+ export async function viewingUpdate(params: {
17
+ accountId: string;
18
+ teamName: string;
19
+ viewingId: number;
20
+ department: Department;
21
+ action: Action;
22
+ text: string;
23
+ feedbackParty?: FeedbackParty;
24
+ }): Promise<string> {
25
+ const { accountId, teamName, viewingId, department, action, text, feedbackParty } = params;
26
+
27
+ if (action === "feedback" && !feedbackParty) {
28
+ throw new Error("feedbackParty is required when action is 'feedback'. Use: buyer, seller, renter, or landlord.");
29
+ }
30
+
31
+ await withTeamKey<LoopBooleanResponse>(
32
+ accountId,
33
+ teamName,
34
+ "viewings",
35
+ "loop-viewing-update",
36
+ async (apiKey) => {
37
+ const suffix = action === "note"
38
+ ? "note"
39
+ : `${feedbackParty}-feedback`;
40
+ const path = `/residential/${department}/viewings/${viewingId}/${suffix}`;
41
+ // Loop expects the text as a StringResponse body
42
+ return loopPost<LoopBooleanResponse>(apiKey, path, { result: text }, "loop-viewing-update", teamName);
43
+ }
44
+ );
45
+
46
+ const actionLabel = action === "note" ? "Note added" : `${feedbackParty} feedback recorded`;
47
+ return `${actionLabel} for viewing ${viewingId} (${department}) via team "${teamName}".`;
48
+ }
@@ -3258,8 +3258,8 @@ async function GET() {
3258
3258
  // app/lib/claude-agent.ts
3259
3259
  import Anthropic from "@anthropic-ai/sdk";
3260
3260
  import { spawn as spawn2 } from "child_process";
3261
- import { resolve as resolve5 } from "path";
3262
- import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync6, mkdirSync as mkdirSync3, createWriteStream, statSync as statSync2, unlinkSync } from "fs";
3261
+ import { resolve as resolve5, join as join4 } from "path";
3262
+ import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync6, mkdirSync as mkdirSync3, createWriteStream, statSync as statSync2, unlinkSync, cpSync } from "fs";
3263
3263
 
3264
3264
  // app/lib/vnc.ts
3265
3265
  import { spawnSync, execFileSync } from "child_process";
@@ -4703,6 +4703,90 @@ function parsePluginFrontmatter(pluginDir) {
4703
4703
  platform
4704
4704
  };
4705
4705
  }
4706
+ function autoDeliverPremiumPlugins(purchasedPlugins) {
4707
+ if (!purchasedPlugins || purchasedPlugins.length === 0) return;
4708
+ const TAG14 = "[premium-auto-deliver]";
4709
+ const stagingRoot = resolve5(PLATFORM_ROOT4, "../premium-plugins");
4710
+ const pluginsDir = resolve5(PLATFORM_ROOT4, "plugins");
4711
+ if (!existsSync6(stagingRoot)) {
4712
+ console.log(`${TAG14} no staging directory \u2014 skipping`);
4713
+ return;
4714
+ }
4715
+ for (const pluginName of purchasedPlugins) {
4716
+ const stagingDir = resolve5(stagingRoot, pluginName);
4717
+ if (!existsSync6(stagingDir)) {
4718
+ console.log(`${TAG14} ${pluginName}: not in staging \u2014 skipping`);
4719
+ continue;
4720
+ }
4721
+ const bundlePath = join4(stagingDir, "BUNDLE.md");
4722
+ const isBundle = existsSync6(bundlePath);
4723
+ if (isBundle) {
4724
+ let bundleRaw;
4725
+ try {
4726
+ bundleRaw = readFileSync5(bundlePath, "utf-8");
4727
+ } catch (err) {
4728
+ console.log(`${TAG14} ${pluginName}: cannot read BUNDLE.md \u2014 ${err instanceof Error ? err.message : String(err)}`);
4729
+ continue;
4730
+ }
4731
+ const fmMatch = bundleRaw.match(/^---\n([\s\S]*?)\n---/);
4732
+ const subPlugins = [];
4733
+ if (fmMatch) {
4734
+ let inPlugins = false;
4735
+ for (const line of fmMatch[1].split("\n")) {
4736
+ if (/^plugins:/.test(line)) {
4737
+ inPlugins = true;
4738
+ continue;
4739
+ }
4740
+ if (inPlugins) {
4741
+ const m = line.match(/^\s+- (.+)/);
4742
+ if (m) {
4743
+ subPlugins.push(m[1].trim());
4744
+ } else {
4745
+ break;
4746
+ }
4747
+ }
4748
+ }
4749
+ }
4750
+ if (subPlugins.length === 0) {
4751
+ console.log(`${TAG14} ${pluginName}: BUNDLE.md has no plugins list \u2014 skipping`);
4752
+ continue;
4753
+ }
4754
+ let delivered = 0;
4755
+ let skipped = 0;
4756
+ for (const sub of subPlugins) {
4757
+ const target = resolve5(pluginsDir, sub);
4758
+ if (existsSync6(resolve5(target, "PLUGIN.md"))) {
4759
+ skipped++;
4760
+ continue;
4761
+ }
4762
+ const source = resolve5(stagingDir, "plugins", sub);
4763
+ if (!existsSync6(source)) {
4764
+ console.log(`${TAG14} ${pluginName}/${sub}: source missing in staging \u2014 skipping`);
4765
+ continue;
4766
+ }
4767
+ try {
4768
+ cpSync(source, target, { recursive: true });
4769
+ delivered++;
4770
+ } catch (err) {
4771
+ console.log(`${TAG14} ${pluginName}/${sub}: copy failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
4772
+ }
4773
+ }
4774
+ console.log(`${TAG14} ${pluginName} (bundle): ${delivered} delivered, ${skipped} already present`);
4775
+ } else {
4776
+ const target = resolve5(pluginsDir, pluginName);
4777
+ if (existsSync6(resolve5(target, "PLUGIN.md"))) {
4778
+ console.log(`${TAG14} ${pluginName}: already present \u2014 skipping`);
4779
+ continue;
4780
+ }
4781
+ try {
4782
+ cpSync(stagingDir, target, { recursive: true });
4783
+ console.log(`${TAG14} ${pluginName} (standalone): delivered`);
4784
+ } catch (err) {
4785
+ console.log(`${TAG14} ${pluginName}: copy failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
4786
+ }
4787
+ }
4788
+ }
4789
+ }
4706
4790
  function assemblePublicPluginContent(pluginDir) {
4707
4791
  const pluginRoot = resolve5(PLATFORM_ROOT4, "plugins", pluginDir);
4708
4792
  const pluginPath = resolve5(pluginRoot, "PLUGIN.md");
@@ -7457,6 +7541,9 @@ ${soul}` : identityPrompt;
7457
7541
  ${isoTimestamp}
7458
7542
  ${humanReadable} (${effectiveTimezone})
7459
7543
  </datetime>`;
7544
+ if (agentType === "admin") {
7545
+ autoDeliverPremiumPlugins(account.config.purchasedPlugins);
7546
+ }
7460
7547
  if (agentType === "admin") {
7461
7548
  if (sessionUserId) {
7462
7549
  baseSystemPrompt += `
@@ -1,54 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopFeedback {
8
- id?: string;
9
- propertyAddress?: string;
10
- viewingDate?: string;
11
- feedback?: string;
12
- rating?: number;
13
- attendeeName?: string;
14
- status?: string;
15
- [key: string]: unknown;
16
- }
17
-
18
- export async function feedbackList(params: {
19
- accountId: string;
20
- teamName?: string;
21
- limit?: number;
22
- }): Promise<string> {
23
- const { accountId, teamName, limit } = params;
24
-
25
- const result = await aggregateAcrossTeams<LoopFeedback>(
26
- accountId,
27
- "feedback",
28
- "loop-feedback-list",
29
- async (apiKey, team) => {
30
- const data = await loopGet<LoopFeedback[]>(
31
- apiKey,
32
- "/feedback",
33
- "loop-feedback-list",
34
- team
35
- );
36
- return Array.isArray(data) ? data : [];
37
- },
38
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
39
- );
40
-
41
- return formatAggregationResult(
42
- result,
43
- (f) => {
44
- const addr = f.propertyAddress ?? "Unknown property";
45
- const date = f.viewingDate ?? "";
46
- const attendee = f.attendeeName ? ` (${f.attendeeName})` : "";
47
- const rating = f.rating != null ? ` ★${f.rating}` : "";
48
- const text = f.feedback ? `: "${f.feedback}"` : "";
49
- const status = f.status ? ` [${f.status}]` : "";
50
- return `- ${addr} ${date}${attendee}${rating}${status}${text}`;
51
- },
52
- "feedback"
53
- );
54
- }
@@ -1,52 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopPerson {
8
- id?: string;
9
- firstName?: string;
10
- lastName?: string;
11
- email?: string;
12
- phone?: string;
13
- type?: string;
14
- [key: string]: unknown;
15
- }
16
-
17
- export async function peopleList(params: {
18
- accountId: string;
19
- search?: string;
20
- teamName?: string;
21
- limit?: number;
22
- }): Promise<string> {
23
- const { accountId, search, teamName, limit } = params;
24
-
25
- const result = await aggregateAcrossTeams<LoopPerson>(
26
- accountId,
27
- "people",
28
- "loop-people-list",
29
- async (apiKey, team) => {
30
- const searchParam = search ? `?search=${encodeURIComponent(search)}` : "";
31
- const data = await loopGet<LoopPerson[]>(
32
- apiKey,
33
- `/people${searchParam}`,
34
- "loop-people-list",
35
- team
36
- );
37
- return Array.isArray(data) ? data : [];
38
- },
39
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
40
- );
41
-
42
- return formatAggregationResult(
43
- result,
44
- (p) => {
45
- const name = [p.firstName, p.lastName].filter(Boolean).join(" ") || "Unknown";
46
- const contact = p.email ?? p.phone ?? "";
47
- const type = p.type ? ` (${p.type})` : "";
48
- return `- ${name}${contact ? ` <${contact}>` : ""}${type}`;
49
- },
50
- "people"
51
- );
52
- }
@@ -1,52 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopProperty {
8
- id?: string;
9
- address?: string;
10
- price?: number;
11
- status?: string;
12
- type?: string;
13
- bedrooms?: number;
14
- bathrooms?: number;
15
- description?: string;
16
- [key: string]: unknown;
17
- }
18
-
19
- export async function propertiesList(params: {
20
- accountId: string;
21
- type?: string;
22
- teamName?: string;
23
- limit?: number;
24
- }): Promise<string> {
25
- const { accountId, type, teamName, limit } = params;
26
-
27
- const result = await aggregateAcrossTeams<LoopProperty>(
28
- accountId,
29
- "properties",
30
- "loop-properties-list",
31
- async (apiKey, team) => {
32
- const path = type && type !== "both"
33
- ? `/properties?type=${encodeURIComponent(type)}`
34
- : "/properties";
35
- const data = await loopGet<LoopProperty[]>(apiKey, path, "loop-properties-list", team);
36
- return Array.isArray(data) ? data : [];
37
- },
38
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
39
- );
40
-
41
- return formatAggregationResult(
42
- result,
43
- (p) => {
44
- const price = p.price ? ` — £${p.price.toLocaleString("en-GB")}` : "";
45
- const beds = p.bedrooms ? ` ${p.bedrooms}bed` : "";
46
- const status = p.status ? ` [${p.status}]` : "";
47
- const propType = p.type ? ` (${p.type})` : "";
48
- return `- ${p.address ?? "Unknown address"}${price}${beds}${propType}${status}`;
49
- },
50
- "properties"
51
- );
52
- }
@@ -1,62 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopViewing {
8
- id?: string;
9
- propertyAddress?: string;
10
- date?: string;
11
- time?: string;
12
- status?: string;
13
- type?: string;
14
- attendeeName?: string;
15
- [key: string]: unknown;
16
- }
17
-
18
- export async function viewingsList(params: {
19
- accountId: string;
20
- type?: string;
21
- teamName?: string;
22
- dateFrom?: string;
23
- dateTo?: string;
24
- limit?: number;
25
- }): Promise<string> {
26
- const { accountId, type, teamName, dateFrom, dateTo, limit } = params;
27
-
28
- const result = await aggregateAcrossTeams<LoopViewing>(
29
- accountId,
30
- "viewings",
31
- "loop-viewings-list",
32
- async (apiKey, team) => {
33
- const queryParts: string[] = [];
34
- if (type && type !== "both") queryParts.push(`type=${encodeURIComponent(type)}`);
35
- if (dateFrom) queryParts.push(`dateFrom=${encodeURIComponent(dateFrom)}`);
36
- if (dateTo) queryParts.push(`dateTo=${encodeURIComponent(dateTo)}`);
37
- const query = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
38
-
39
- const data = await loopGet<LoopViewing[]>(
40
- apiKey,
41
- `/viewings${query}`,
42
- "loop-viewings-list",
43
- team
44
- );
45
- return Array.isArray(data) ? data : [];
46
- },
47
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
48
- );
49
-
50
- return formatAggregationResult(
51
- result,
52
- (v) => {
53
- const addr = v.propertyAddress ?? "Unknown property";
54
- const when = [v.date, v.time].filter(Boolean).join(" ");
55
- const status = v.status ? ` [${v.status}]` : "";
56
- const attendee = v.attendeeName ? ` — ${v.attendeeName}` : "";
57
- const viewType = v.type ? ` (${v.type})` : "";
58
- return `- ${addr} — ${when || "No date"}${viewType}${attendee}${status}`;
59
- },
60
- "viewings"
61
- );
62
- }