@rubytech/create-realagent-code 0.1.615 → 0.1.616

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 (193) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/aeo-llms-txt-writer/dist/__tests__/write-llms-txt.test.d.ts +2 -0
  3. package/payload/platform/lib/aeo-llms-txt-writer/dist/__tests__/write-llms-txt.test.d.ts.map +1 -0
  4. package/payload/platform/lib/aeo-llms-txt-writer/dist/__tests__/write-llms-txt.test.js +291 -0
  5. package/payload/platform/lib/aeo-llms-txt-writer/dist/__tests__/write-llms-txt.test.js.map +1 -0
  6. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts +13 -1
  7. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.d.ts.map +1 -1
  8. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js +127 -18
  9. package/payload/platform/lib/aeo-llms-txt-writer/dist/index.js.map +1 -1
  10. package/payload/platform/lib/aeo-llms-txt-writer/src/__tests__/write-llms-txt.test.ts +391 -0
  11. package/payload/platform/lib/aeo-llms-txt-writer/src/index.ts +156 -19
  12. package/payload/platform/lib/aeo-llms-txt-writer/vitest.config.ts +10 -0
  13. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +15 -1
  14. package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts.map +1 -1
  15. package/payload/platform/lib/mcp-spawn-tee/dist/index.js +129 -7
  16. package/payload/platform/lib/mcp-spawn-tee/dist/index.js.map +1 -1
  17. package/payload/platform/lib/mcp-spawn-tee/src/__tests__/spawn-tee.test.ts +227 -0
  18. package/payload/platform/lib/mcp-spawn-tee/src/index.ts +133 -6
  19. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +129 -7
  20. package/payload/platform/plugins/admin/mcp/dist/index.js +11 -3
  21. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  22. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts +3 -0
  23. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.d.ts.map +1 -1
  24. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js +38 -20
  25. package/payload/platform/plugins/admin/mcp/dist/tools/publish-site.js.map +1 -1
  26. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +6 -5
  27. package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +3 -0
  28. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +8 -0
  29. package/payload/platform/plugins/aeo/PLUGIN.md +1 -1
  30. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +129 -7
  31. package/payload/platform/plugins/aeo/mcp/dist/index.js +17 -10
  32. package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -1
  33. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +129 -7
  34. package/payload/platform/plugins/connector/lib/mcp-spawn-tee/index.js +129 -7
  35. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +129 -7
  36. package/payload/platform/plugins/dispatch/lib/mcp-spawn-tee/index.js +129 -7
  37. package/payload/platform/plugins/docs/references/aeo.md +4 -3
  38. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  39. package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +129 -7
  40. package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +129 -7
  41. package/payload/platform/plugins/google/lib/mcp-spawn-tee/index.js +129 -7
  42. package/payload/platform/plugins/graph-viewer/lib/mcp-spawn-tee/index.js +129 -7
  43. package/payload/platform/plugins/inventory/lib/mcp-spawn-tee/index.js +129 -7
  44. package/payload/platform/plugins/ledger/lib/mcp-spawn-tee/index.js +129 -7
  45. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +129 -7
  46. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +129 -7
  47. package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +129 -7
  48. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +129 -7
  49. package/payload/platform/plugins/scheduling/PLUGIN.md +3 -4
  50. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +129 -7
  51. package/payload/platform/plugins/scheduling/mcp/dist/index.js +0 -6
  52. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  53. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js +65 -20
  54. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-audits.test.js.map +1 -1
  55. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-classification.test.js +20 -0
  56. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/gate-classification.test.js.map +1 -1
  57. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts +12 -4
  58. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.d.ts.map +1 -1
  59. package/payload/platform/plugins/scheduling/mcp/dist/lib/gate.js.map +1 -1
  60. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.d.ts.map +1 -1
  61. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js +39 -6
  62. package/payload/platform/plugins/scheduling/mcp/dist/lib/schedule-audit.js.map +1 -1
  63. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js +21 -6
  64. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/gate-dispatch-wiring.test.js.map +1 -1
  65. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +26 -5
  66. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  67. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-waiver.test.js +17 -51
  68. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-waiver.test.js.map +1 -1
  69. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js +6 -4
  70. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-gate-write.test.js.map +1 -1
  71. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js +113 -1
  72. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/scheduling-gate.test.js.map +1 -1
  73. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +8 -18
  74. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
  75. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +14 -27
  76. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  77. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.d.ts.map +1 -1
  78. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js +125 -56
  79. package/payload/platform/plugins/scheduling/mcp/dist/tools/scheduling-gate.js.map +1 -1
  80. package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/index.js +129 -7
  81. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +129 -7
  82. package/payload/platform/plugins/voice-mirror/lib/mcp-spawn-tee/index.js +129 -7
  83. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +129 -7
  84. package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +129 -7
  85. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +129 -7
  86. package/payload/platform/services/claude-session-manager/dist/index.js +17 -0
  87. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  88. package/payload/platform/services/claude-session-manager/dist/mcp-helper-census.d.ts +80 -0
  89. package/payload/platform/services/claude-session-manager/dist/mcp-helper-census.d.ts.map +1 -0
  90. package/payload/platform/services/claude-session-manager/dist/mcp-helper-census.js +201 -0
  91. package/payload/platform/services/claude-session-manager/dist/mcp-helper-census.js.map +1 -0
  92. package/payload/premium-plugins/real-agent/plugins/buyers/lib/mcp-spawn-tee/index.js +129 -7
  93. package/payload/premium-plugins/real-agent/plugins/estate-sales/lib/mcp-spawn-tee/index.js +129 -7
  94. package/payload/premium-plugins/real-agent/plugins/loop/PLUGIN.md +12 -0
  95. package/payload/premium-plugins/real-agent/plugins/loop/lib/mcp-spawn-tee/index.js +129 -7
  96. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js +13 -0
  97. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js.map +1 -1
  98. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/field-census.d.ts +22 -0
  99. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/field-census.d.ts.map +1 -0
  100. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/field-census.js +81 -0
  101. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/field-census.js.map +1 -0
  102. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-api.d.ts +17 -5
  103. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-api.d.ts.map +1 -1
  104. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-api.js +90 -17
  105. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-api.js.map +1 -1
  106. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-schema-keys.d.ts +2 -0
  107. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-schema-keys.d.ts.map +1 -0
  108. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-schema-keys.js +1010 -0
  109. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/lib/loop-schema-keys.js.map +1 -0
  110. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/auto-responder.js +2 -2
  111. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/auto-responder.js.map +1 -1
  112. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/customer-preferences.js +3 -3
  113. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/customer-preferences.js.map +1 -1
  114. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/feedback.d.ts +1 -0
  115. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/feedback.d.ts.map +1 -1
  116. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/feedback.js +5 -5
  117. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/feedback.js.map +1 -1
  118. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match-batch.d.ts +1 -0
  119. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match-batch.d.ts.map +1 -1
  120. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match-batch.js +2 -2
  121. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match-batch.js.map +1 -1
  122. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match.d.ts +1 -0
  123. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match.d.ts.map +1 -1
  124. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match.js +4 -4
  125. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/marketing-match.js.map +1 -1
  126. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-detail.d.ts +1 -0
  127. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-detail.d.ts.map +1 -1
  128. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-detail.js +3 -3
  129. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-detail.js.map +1 -1
  130. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-search.d.ts +1 -0
  131. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-search.d.ts.map +1 -1
  132. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-search.js +3 -3
  133. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/people-search.js.map +1 -1
  134. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-detail.d.ts +1 -0
  135. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-detail.d.ts.map +1 -1
  136. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-detail.js +13 -6
  137. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-detail.js.map +1 -1
  138. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-listed.d.ts +1 -0
  139. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-listed.d.ts.map +1 -1
  140. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-listed.js +3 -3
  141. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-listed.js.map +1 -1
  142. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-search.d.ts +1 -0
  143. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-search.d.ts.map +1 -1
  144. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-search.js +3 -3
  145. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-search.js.map +1 -1
  146. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-sold.d.ts +1 -0
  147. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-sold.d.ts.map +1 -1
  148. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-sold.js +3 -3
  149. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/property-sold.js.map +1 -1
  150. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/supplier.js +4 -4
  151. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/supplier.js.map +1 -1
  152. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-availability.d.ts +1 -0
  153. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-availability.d.ts.map +1 -1
  154. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-availability.js +3 -3
  155. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-availability.js.map +1 -1
  156. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-info.d.ts +1 -0
  157. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-info.d.ts.map +1 -1
  158. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-info.js +3 -3
  159. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/team-info.js.map +1 -1
  160. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-detail.d.ts +1 -0
  161. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-detail.d.ts.map +1 -1
  162. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-detail.js +3 -3
  163. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-detail.js.map +1 -1
  164. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-search.d.ts +1 -0
  165. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-search.d.ts.map +1 -1
  166. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-search.js +3 -3
  167. package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/tools/viewing-search.js.map +1 -1
  168. package/payload/premium-plugins/real-agent/plugins/loop/mcp/package.json +2 -1
  169. package/payload/premium-plugins/real-agent/plugins/loop/mcp/scripts/generate-loop-schema-keys.mjs +87 -0
  170. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/__tests__/new-tool-shape.test.ts +1 -1
  171. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/__tests__/read-fidelity.test.ts +303 -0
  172. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/__tests__/swagger-write-coverage.test.ts +6 -6
  173. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/index.ts +13 -0
  174. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/lib/field-census.ts +86 -0
  175. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/lib/loop-api.ts +116 -17
  176. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/lib/loop-schema-keys.ts +1010 -0
  177. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/auto-responder.ts +2 -2
  178. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/customer-preferences.ts +3 -3
  179. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/feedback.ts +6 -4
  180. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/marketing-match-batch.ts +4 -2
  181. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/marketing-match.ts +6 -4
  182. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/people-detail.ts +5 -3
  183. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/people-search.ts +5 -3
  184. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/property-detail.ts +17 -7
  185. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/property-listed.ts +5 -3
  186. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/property-search.ts +5 -3
  187. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/property-sold.ts +5 -3
  188. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/supplier.ts +4 -4
  189. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/team-availability.ts +5 -3
  190. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/team-info.ts +6 -3
  191. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/viewing-detail.ts +5 -3
  192. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/tools/viewing-search.ts +5 -3
  193. package/payload/premium-plugins/real-agent/plugins/property-data/lib/mcp-spawn-tee/index.js +129 -7
@@ -1,4 +1,4 @@
1
- import { loopGet, loopPut, withTeamKey } from "../lib/loop-api.js";
1
+ import { formatSingleTeamRead, loopGet, loopPut, withTeamKey } from "../lib/loop-api.js";
2
2
 
3
3
  type AutoResponderAction = "get" | "answers" | "details" | "refer";
4
4
 
@@ -40,7 +40,7 @@ export async function autoResponder(params: {
40
40
  "loop-auto-responder", teamName
41
41
  )
42
42
  );
43
- return JSON.stringify(result, null, 2);
43
+ return formatSingleTeamRead(result, JSON.stringify(result, null, 2));
44
44
  }
45
45
 
46
46
  if (action === "answers") {
@@ -1,4 +1,4 @@
1
- import { loopGet, loopPost, withTeamKey } from "../lib/loop-api.js";
1
+ import { formatSingleTeamRead, loopGet, loopPost, withTeamKey } from "../lib/loop-api.js";
2
2
 
3
3
  type PreferencesAction = "read" | "write";
4
4
 
@@ -40,9 +40,9 @@ export async function customerPreferences(params: {
40
40
  );
41
41
 
42
42
  if (!result || (Array.isArray(result) && result.length === 0)) {
43
- return `No preferences found for person ${personCode} via team "${teamName}".`;
43
+ return formatSingleTeamRead(result, `No preferences found for person ${personCode} via team "${teamName}".`);
44
44
  }
45
- return JSON.stringify(result, null, 2);
45
+ return formatSingleTeamRead(result, JSON.stringify(result, null, 2));
46
46
  }
47
47
 
48
48
  if (action === "write") {
@@ -1,4 +1,5 @@
1
1
  import {
2
+ formatSingleTeamRead,
2
3
  loopGet,
3
4
  loopPost,
4
5
  withTeamKey,
@@ -33,8 +34,9 @@ export async function feedbackGet(params: {
33
34
  teamName: string;
34
35
  viewingId: number;
35
36
  department: Department;
37
+ raw?: boolean;
36
38
  }): Promise<string> {
37
- const { accountId, teamName, viewingId, department } = params;
39
+ const { accountId, teamName, viewingId, department, raw } = params;
38
40
 
39
41
  const result = await withTeamKey<LoopViewingFeedback>(
40
42
  accountId,
@@ -43,12 +45,12 @@ export async function feedbackGet(params: {
43
45
  "loop-feedback-get",
44
46
  async (apiKey) => {
45
47
  const path = `/feedback/residential/${department}/viewings/${viewingId}`;
46
- return loopGet<LoopViewingFeedback>(apiKey, path, "loop-feedback-get", teamName);
48
+ return loopGet<LoopViewingFeedback>(apiKey, path, "loop-feedback-get", teamName, { raw });
47
49
  }
48
50
  );
49
51
 
50
52
  if (!result || (Array.isArray(result) && result.length === 0)) {
51
- return `No feedback found for viewing ${viewingId} (${department}) via team "${teamName}".`;
53
+ return formatSingleTeamRead(result, `No feedback found for viewing ${viewingId} (${department}) via team "${teamName}".`, { raw });
52
54
  }
53
55
 
54
56
  const f = result;
@@ -59,7 +61,7 @@ export async function feedbackGet(params: {
59
61
  if (f.rating != null) lines.push(`Rating: ★${f.rating}`);
60
62
  if (f.status) lines.push(`Status: ${f.status}`);
61
63
  if (f.feedback) lines.push(`Feedback: ${f.feedback}`);
62
- return lines.join("\n");
64
+ return formatSingleTeamRead(result, lines.join("\n"), { raw });
63
65
  }
64
66
 
65
67
  export async function feedbackSubmit(params: {
@@ -25,8 +25,9 @@ export async function marketingMatchBatch(params: {
25
25
  propertyIds: number[];
26
26
  department: Department;
27
27
  teamName?: string;
28
+ raw?: boolean;
28
29
  }): Promise<string> {
29
- const { accountId, propertyIds, department, teamName } = params;
30
+ const { raw, accountId, propertyIds, department, teamName } = params;
30
31
 
31
32
  const result = await aggregateAcrossTeams<LoopMatchingSummary>(
32
33
  accountId,
@@ -48,6 +49,7 @@ export async function marketingMatchBatch(params: {
48
49
  const beds = p.bedrooms ? ` ${p.bedrooms}bed` : "";
49
50
  return `- ${p.address ?? "Unknown"}${price}${beds}`;
50
51
  },
51
- "matching properties"
52
+ "matching properties",
53
+ { raw }
52
54
  );
53
55
  }
@@ -38,8 +38,9 @@ export async function marketingMatchDetail(params: {
38
38
  department: Department;
39
39
  includeTeamProfile?: boolean;
40
40
  teamName?: string;
41
+ raw?: boolean;
41
42
  }): Promise<string> {
42
- const { accountId, propertyId, department, includeTeamProfile = false, teamName } = params;
43
+ const { raw, accountId, propertyId, department, includeTeamProfile = false, teamName } = params;
43
44
 
44
45
  const result = await aggregateAcrossTeams<LoopMatchingProperty>(
45
46
  accountId,
@@ -48,11 +49,11 @@ export async function marketingMatchDetail(params: {
48
49
  async (apiKey, team) => {
49
50
  const prefix = department === "lettings" ? "/marketing/rentals" : "/marketing";
50
51
  const path = `${prefix}/matching/${propertyId}`;
51
- const data = await loopGet<LoopMatchingProperty>(apiKey, path, "loop-marketing-match", team);
52
+ const data = await loopGet<LoopMatchingProperty>(apiKey, path, "loop-marketing-match", team, { raw });
52
53
  if (data && typeof data === "object" && !Array.isArray(data)) {
53
54
  if (includeTeamProfile) {
54
55
  const profilePath = `${prefix}/matching/${propertyId}/team-profile`;
55
- const profile = await loopGet<LoopMatchingTeamProfile>(apiKey, profilePath, "loop-marketing-match", team).catch(() => null);
56
+ const profile = await loopGet<LoopMatchingTeamProfile>(apiKey, profilePath, "loop-marketing-match", team, { raw }).catch(() => null);
56
57
  if (profile) {
57
58
  (data as Record<string, unknown>)._teamProfile = profile;
58
59
  }
@@ -79,6 +80,7 @@ export async function marketingMatchDetail(params: {
79
80
  }
80
81
  return lines.join("\n");
81
82
  },
82
- "matching property details"
83
+ "matching property details",
84
+ { raw }
83
85
  );
84
86
  }
@@ -119,8 +119,9 @@ export async function peopleDetail(params: {
119
119
  personId: number;
120
120
  role?: PeopleRole;
121
121
  teamName?: string;
122
+ raw?: boolean;
122
123
  }): Promise<string> {
123
- const { accountId, personId, role, teamName } = params;
124
+ const { raw, accountId, personId, role, teamName } = params;
124
125
 
125
126
  const result = await aggregateAcrossTeams<Record<string, unknown>>(
126
127
  accountId,
@@ -129,7 +130,7 @@ export async function peopleDetail(params: {
129
130
  async (apiKey, team) => {
130
131
  const basePath = role ? `/people/${role}` : "/people";
131
132
  const path = `${basePath}/${personId}`;
132
- const data = await loopGet<Record<string, unknown>>(apiKey, path, "loop-people-detail", team);
133
+ const data = await loopGet<Record<string, unknown>>(apiKey, path, "loop-people-detail", team, { raw });
133
134
  if (data && typeof data === "object" && !Array.isArray(data)) {
134
135
  return [data];
135
136
  }
@@ -141,7 +142,8 @@ export async function peopleDetail(params: {
141
142
  return formatAggregationResult(
142
143
  result,
143
144
  (record) => formatDetailRecord(record, role),
144
- "person details"
145
+ "person details",
146
+ { raw }
145
147
  );
146
148
  }
147
149
 
@@ -89,8 +89,9 @@ export async function peopleSearch(params: {
89
89
  maxRent?: number;
90
90
  teamName?: string;
91
91
  limit?: number;
92
+ raw?: boolean;
92
93
  }): Promise<string> {
93
- const {
94
+ const { raw,
94
95
  accountId, role, searchTerm,
95
96
  maxPrice, minBeds, searchAreas, propertyTypes,
96
97
  startDate, endDate, minPrice, maxRent,
@@ -131,7 +132,7 @@ export async function peopleSearch(params: {
131
132
  const query = qp.length > 0 ? `?${qp.join("&")}` : "";
132
133
  const basePath = role ? `/people/${role}` : "/people";
133
134
  const path = `${basePath}${query}`;
134
- const data = await loopGet<Record<string, unknown>[]>(apiKey, path, "loop-people-search", team);
135
+ const data = await loopGet<Record<string, unknown>[]>(apiKey, path, "loop-people-search", team, { raw });
135
136
  return Array.isArray(data) ? data : [];
136
137
  },
137
138
  { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
@@ -141,7 +142,8 @@ export async function peopleSearch(params: {
141
142
  return formatAggregationResult(
142
143
  result,
143
144
  (record) => formatPersonRecord(record, role),
144
- entityName
145
+ entityName,
146
+ { raw }
145
147
  );
146
148
  }
147
149
 
@@ -12,7 +12,8 @@ import {
12
12
  // dateWithdrawn, shortDescription, fullDescription, bathrooms,
13
13
  // bedrooms, receptionRooms, price, priceQualifier, latitude,
14
14
  // longitude, parking, outsideSpace, councilTaxBand, floorArea,
15
- // tenure, serviceCharge, groundRent, features[], images[],
15
+ // tenure, serviceCharge, groundRent, saleBy, amlVerified,
16
+ // features[], images[],
16
17
  // marketingFlag_*, creatingAgentId
17
18
  // ────────────────────────────────────────────────────────────────
18
19
  interface LoopPropertyDetail {
@@ -49,6 +50,8 @@ interface LoopPropertyDetail {
49
50
  tenure?: string;
50
51
  serviceCharge?: number;
51
52
  groundRent?: number;
53
+ saleBy?: string;
54
+ amlVerified?: string;
52
55
  features?: string[];
53
56
  images?: { url: string; mimeType?: string }[];
54
57
  creatingAgentId?: string;
@@ -64,8 +67,9 @@ export async function propertyDetail(params: {
64
67
  department: Department;
65
68
  previewHash?: number;
66
69
  teamName?: string;
70
+ raw?: boolean;
67
71
  }): Promise<string> {
68
- const { accountId, propertyId, department, previewHash, teamName } = params;
72
+ const { raw, accountId, propertyId, department, previewHash, teamName } = params;
69
73
 
70
74
  const result = await aggregateAcrossTeams<LoopPropertyDetail>(
71
75
  accountId,
@@ -75,7 +79,7 @@ export async function propertyDetail(params: {
75
79
  const path = previewHash
76
80
  ? `/property/residential/${department}/${propertyId}/preview/${previewHash}`
77
81
  : `/property/residential/${department}/${propertyId}`;
78
- const data = await loopGet<LoopPropertyDetail>(apiKey, path, "loop-property-detail", team);
82
+ const data = await loopGet<LoopPropertyDetail>(apiKey, path, "loop-property-detail", team, { raw });
79
83
  if (data && typeof data === "object" && !Array.isArray(data)) {
80
84
  return [data];
81
85
  }
@@ -108,12 +112,17 @@ export async function propertyDetail(params: {
108
112
  if (p.bathrooms != null) lines.push(`Bathrooms: ${p.bathrooms}`);
109
113
  if (p.receptionRooms != null) lines.push(`Reception rooms: ${p.receptionRooms}`);
110
114
  if (p.floorArea) lines.push(`Floor area: ${p.floorArea} sq ft`);
111
- if (p.tenure && p.tenure !== "None") lines.push(`Tenure: ${p.tenure}`);
115
+ if (p.tenure != null) lines.push(`Tenure: ${p.tenure}`);
112
116
  if (p.councilTaxBand) lines.push(`Council Tax: Band ${p.councilTaxBand}`);
113
117
  if (p.parking) lines.push(`Parking: ${p.parking}`);
114
118
  if (p.outsideSpace) lines.push(`Outside: ${p.outsideSpace}`);
115
- if (p.serviceCharge) lines.push(`Service charge: £${p.serviceCharge}`);
116
- if (p.groundRent) lines.push(`Ground rent: £${p.groundRent}`);
119
+ // Presence, not truthiness. A service charge of zero is a fact; a
120
+ // service charge nobody entered is a compliance failure. Dropping the
121
+ // zero made the two identical and the pre-flight unbuildable.
122
+ if (p.serviceCharge != null) lines.push(`Service charge: £${p.serviceCharge}`);
123
+ if (p.groundRent != null) lines.push(`Ground rent: £${p.groundRent}`);
124
+ if (p.saleBy) lines.push(`Sale method: ${p.saleBy}`);
125
+ if (p.amlVerified) lines.push(`AML check: ${p.amlVerified}`);
117
126
 
118
127
  // Key dates
119
128
  const dates: string[] = [];
@@ -140,6 +149,7 @@ export async function propertyDetail(params: {
140
149
 
141
150
  return lines.join("\n");
142
151
  },
143
- "property details"
152
+ "property details",
153
+ { raw }
144
154
  );
145
155
  }
@@ -41,8 +41,9 @@ export async function propertyListed(params: {
41
41
  department?: Department;
42
42
  teamName?: string;
43
43
  limit?: number;
44
+ raw?: boolean;
44
45
  }): Promise<string> {
45
- const { accountId, channel, department = "both", teamName, limit } = params;
46
+ const { raw, accountId, channel, department = "both", teamName, limit } = params;
46
47
 
47
48
  const result = await aggregateAcrossTeams<LoopPropertyListing>(
48
49
  accountId,
@@ -55,7 +56,7 @@ export async function propertyListed(params: {
55
56
 
56
57
  for (const dept of depts) {
57
58
  const path = `/property/residential/${dept}/listed/${channel}`;
58
- const data = await loopGet<LoopPropertyListing[]>(apiKey, path, "loop-property-listed", team);
59
+ const data = await loopGet<LoopPropertyListing[]>(apiKey, path, "loop-property-listed", team, { raw });
59
60
  if (Array.isArray(data)) all.push(...data);
60
61
  }
61
62
 
@@ -76,6 +77,7 @@ export async function propertyListed(params: {
76
77
  const photos = p.images?.length ? ` ${p.images.length} photo${p.images.length !== 1 ? "s" : ""}` : "";
77
78
  return `- ${addr}${id}${price}${beds}${propType}${status}${photos}`;
78
79
  },
79
- `${channel} listings`
80
+ `${channel} listings`,
81
+ { raw }
80
82
  );
81
83
  }
@@ -40,8 +40,9 @@ export async function propertySearch(params: {
40
40
  propertyTypes?: string;
41
41
  teamName?: string;
42
42
  limit?: number;
43
+ raw?: boolean;
43
44
  }): Promise<string> {
44
- const {
45
+ const { raw,
45
46
  accountId, department = "both", searchTerm, minPrice, maxPrice,
46
47
  minBedrooms, maxBedrooms, propertyStatuses, propertyTypes,
47
48
  teamName, limit,
@@ -68,7 +69,7 @@ export async function propertySearch(params: {
68
69
 
69
70
  const query = qp.length > 0 ? `?${qp.join("&")}` : "";
70
71
  const path = `/property/residential/${dept}${query}`;
71
- const data = await loopGet<LoopPropertySummary[]>(apiKey, path, "loop-property-search", team);
72
+ const data = await loopGet<LoopPropertySummary[]>(apiKey, path, "loop-property-search", team, { raw });
72
73
  if (Array.isArray(data)) all.push(...data);
73
74
  }
74
75
  return all;
@@ -87,6 +88,7 @@ export async function propertySearch(params: {
87
88
  const offers = p.offerCount ? ` ${p.offerCount} offer${p.offerCount !== 1 ? "s" : ""}` : "";
88
89
  return `- ${p.propertyAddress ?? "Unknown address"}${id}${price}${beds}${propType}${status}${offers}`;
89
90
  },
90
- "properties"
91
+ "properties",
92
+ { raw }
91
93
  );
92
94
  }
@@ -36,8 +36,9 @@ export async function propertySold(params: {
36
36
  channel: Channel;
37
37
  teamName?: string;
38
38
  limit?: number;
39
+ raw?: boolean;
39
40
  }): Promise<string> {
40
- const { accountId, channel, teamName, limit } = params;
41
+ const { raw, accountId, channel, teamName, limit } = params;
41
42
 
42
43
  const result = await aggregateAcrossTeams<LoopPropertyListing>(
43
44
  accountId,
@@ -45,7 +46,7 @@ export async function propertySold(params: {
45
46
  "loop-property-sold",
46
47
  async (apiKey, team) => {
47
48
  const path = `/property/residential/sold/${channel}`;
48
- const data = await loopGet<LoopPropertyListing[]>(apiKey, path, "loop-property-sold", team);
49
+ const data = await loopGet<LoopPropertyListing[]>(apiKey, path, "loop-property-sold", team, { raw });
49
50
  return Array.isArray(data) ? data : [];
50
51
  },
51
52
  { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
@@ -62,6 +63,7 @@ export async function propertySold(params: {
62
63
  const status = p.status ? ` [${p.status}]` : "";
63
64
  return `- ${addr}${id}${price}${beds}${propType}${status}`;
64
65
  },
65
- `${channel} sold`
66
+ `${channel} sold`,
67
+ { raw }
66
68
  );
67
69
  }
@@ -1,4 +1,4 @@
1
- import { loopGet, loopPost, loopPut, withTeamKey } from "../lib/loop-api.js";
1
+ import { formatSingleTeamRead, loopGet, loopPost, loopPut, withTeamKey } from "../lib/loop-api.js";
2
2
 
3
3
  type SupplierAction =
4
4
  | "maintenance-jobs"
@@ -56,7 +56,7 @@ export async function supplier(params: {
56
56
  );
57
57
  }
58
58
  );
59
- return JSON.stringify(result, null, 2);
59
+ return formatSingleTeamRead(result, JSON.stringify(result, null, 2));
60
60
  }
61
61
 
62
62
  if (action === "maintenance-complete") {
@@ -82,7 +82,7 @@ export async function supplier(params: {
82
82
  );
83
83
  }
84
84
  );
85
- return JSON.stringify(result, null, 2);
85
+ return formatSingleTeamRead(result, JSON.stringify(result, null, 2));
86
86
  }
87
87
 
88
88
  if (action === "maintenance-submit-quote") {
@@ -109,7 +109,7 @@ export async function supplier(params: {
109
109
  );
110
110
  }
111
111
  );
112
- return JSON.stringify(result, null, 2);
112
+ return formatSingleTeamRead(result, JSON.stringify(result, null, 2));
113
113
  }
114
114
 
115
115
  if (action === "board-complete") {
@@ -20,8 +20,9 @@ export async function teamAvailability(params: {
20
20
  agentId: string;
21
21
  searchDate: string;
22
22
  teamName?: string;
23
+ raw?: boolean;
23
24
  }): Promise<string> {
24
- const { accountId, agentId, searchDate, teamName } = params;
25
+ const { raw, accountId, agentId, searchDate, teamName } = params;
25
26
 
26
27
  const result = await aggregateAcrossTeams<LoopTimeRange>(
27
28
  accountId,
@@ -29,7 +30,7 @@ export async function teamAvailability(params: {
29
30
  "loop-team-availability",
30
31
  async (apiKey, team) => {
31
32
  const path = `/team/${encodeURIComponent(agentId)}/availability/${encodeURIComponent(searchDate)}`;
32
- const data = await loopGet<LoopTimeRange[]>(apiKey, path, "loop-team-availability", team);
33
+ const data = await loopGet<LoopTimeRange[]>(apiKey, path, "loop-team-availability", team, { raw });
33
34
  return Array.isArray(data) ? data : [];
34
35
  },
35
36
  { teamName }
@@ -42,7 +43,8 @@ export async function teamAvailability(params: {
42
43
  const end = slot.end ? formatTime(slot.end) : "?";
43
44
  return `- ${start} — ${end}`;
44
45
  },
45
- `availability slots for ${searchDate}`
46
+ `availability slots for ${searchDate}`,
47
+ { raw }
46
48
  );
47
49
  }
48
50
 
@@ -43,8 +43,9 @@ interface LoopTeamMember {
43
43
  export async function teamInfo(params: {
44
44
  accountId: string;
45
45
  teamName?: string;
46
+ raw?: boolean;
46
47
  }): Promise<string> {
47
- const { accountId, teamName } = params;
48
+ const { raw, accountId, teamName } = params;
48
49
 
49
50
  const result = await aggregateAcrossTeams<LoopTeam>(
50
51
  accountId,
@@ -55,7 +56,8 @@ export async function teamInfo(params: {
55
56
  apiKey,
56
57
  "/team",
57
58
  "loop-team-info",
58
- team
59
+ team,
60
+ { raw }
59
61
  );
60
62
  // /team returns a single object, not an array
61
63
  if (data && typeof data === "object" && !Array.isArray(data)) {
@@ -90,6 +92,7 @@ export async function teamInfo(params: {
90
92
 
91
93
  return lines.join("\n");
92
94
  },
93
- "teams"
95
+ "teams",
96
+ { raw }
94
97
  );
95
98
  }
@@ -81,8 +81,9 @@ export async function viewingDetail(params: {
81
81
  viewingId: number;
82
82
  department: Department;
83
83
  teamName?: string;
84
+ raw?: boolean;
84
85
  }): Promise<string> {
85
- const { accountId, viewingId, department, teamName } = params;
86
+ const { raw, accountId, viewingId, department, teamName } = params;
86
87
 
87
88
  const result = await aggregateAcrossTeams<LoopViewingDetail>(
88
89
  accountId,
@@ -90,7 +91,7 @@ export async function viewingDetail(params: {
90
91
  "loop-viewing-detail",
91
92
  async (apiKey, team) => {
92
93
  const path = `/residential/${department}/viewings/${viewingId}`;
93
- const data = await loopGet<LoopViewingDetail>(apiKey, path, "loop-viewing-detail", team);
94
+ const data = await loopGet<LoopViewingDetail>(apiKey, path, "loop-viewing-detail", team, { raw });
94
95
  if (data && typeof data === "object" && !Array.isArray(data)) {
95
96
  return [data];
96
97
  }
@@ -160,7 +161,8 @@ export async function viewingDetail(params: {
160
161
 
161
162
  return lines.join("\n");
162
163
  },
163
- "viewing details"
164
+ "viewing details",
165
+ { raw }
164
166
  );
165
167
  }
166
168
 
@@ -34,8 +34,9 @@ export async function viewingSearch(params: {
34
34
  status?: string;
35
35
  teamName?: string;
36
36
  limit?: number;
37
+ raw?: boolean;
37
38
  }): Promise<string> {
38
- const {
39
+ const { raw,
39
40
  accountId, department = "both", searchTerm,
40
41
  appointmentStartDate, appointmentEndDate, status,
41
42
  teamName, limit,
@@ -59,7 +60,7 @@ export async function viewingSearch(params: {
59
60
 
60
61
  const query = qp.length > 0 ? `?${qp.join("&")}` : "";
61
62
  const path = `/residential/${dept}/viewings${query}`;
62
- const data = await loopGet<LoopViewingSummary[]>(apiKey, path, "loop-viewing-search", team);
63
+ const data = await loopGet<LoopViewingSummary[]>(apiKey, path, "loop-viewing-search", team, { raw });
63
64
  if (Array.isArray(data)) all.push(...data);
64
65
  }
65
66
  return all;
@@ -81,7 +82,8 @@ export async function viewingSearch(params: {
81
82
  const viewType = v.type ? ` (${v.type})` : "";
82
83
  return `- ${addr}${id} — ${when}${viewType}${buyer}${viewStatus}`;
83
84
  },
84
- "viewings"
85
+ "viewings",
86
+ { raw }
85
87
  );
86
88
  }
87
89