@agentprojectcontext/apx 1.33.1 → 1.35.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.
Files changed (208) hide show
  1. package/package.json +1 -1
  2. package/skills/apx/SKILL.md +49 -61
  3. package/src/core/agent/a2a/reply.js +48 -0
  4. package/src/core/agent/build-agent-system.js +136 -59
  5. package/src/core/agent/channels/voice-context.js +98 -0
  6. package/src/core/agent/memory.js +2 -1
  7. package/src/core/agent/prompt-builder.js +178 -124
  8. package/src/core/agent/prompts/channels/code.md +12 -10
  9. package/src/core/agent/prompts/channels/desktop.md +5 -32
  10. package/src/core/agent/prompts/channels/telegram.md +4 -15
  11. package/src/core/agent/prompts/channels/web_code.md +11 -11
  12. package/src/core/agent/prompts/core/agent-base.md +24 -0
  13. package/src/core/agent/prompts/core/project-agent.md +11 -0
  14. package/src/core/agent/prompts/core/super-agent.md +21 -0
  15. package/src/core/agent/prompts/discipline/action.md +10 -0
  16. package/src/core/agent/prompts/discipline/single-segment.md +6 -0
  17. package/src/core/agent/prompts/discipline/two-segment.md +11 -0
  18. package/src/core/agent/prompts/modes/code-build.md +1 -0
  19. package/src/core/agent/prompts/modes/code-plan.md +1 -0
  20. package/src/core/agent/prompts/modes/index.js +28 -0
  21. package/src/core/agent/self-memory.js +43 -1
  22. package/src/core/agent/skills/index-store.js +307 -0
  23. package/src/core/agent/skills/index.js +15 -1
  24. package/src/core/agent/skills/inspector.js +317 -0
  25. package/src/core/agent/skills/loader.js +22 -18
  26. package/src/core/agent/stream/turn-accumulator.js +73 -0
  27. package/src/core/agent/suggestions.js +37 -0
  28. package/src/core/agent/super-agent.js +7 -1
  29. package/src/core/agent/tools/handlers/_git.js +50 -0
  30. package/src/core/agent/tools/handlers/add-project.js +5 -2
  31. package/src/core/agent/tools/handlers/call-runtime.js +3 -2
  32. package/src/core/agent/tools/handlers/git-diff.js +44 -0
  33. package/src/core/agent/tools/handlers/git-log.js +38 -0
  34. package/src/core/agent/tools/handlers/git-show.js +34 -0
  35. package/src/core/agent/tools/handlers/git-status.js +61 -0
  36. package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
  37. package/src/core/agent/tools/helpers.js +2 -2
  38. package/src/core/agent/tools/names.js +169 -0
  39. package/src/core/agent/tools/registry-bridge.js +6 -14
  40. package/src/core/agent/tools/registry.js +103 -69
  41. package/src/core/apc/context-copy.js +27 -0
  42. package/src/core/apc/notes.js +19 -0
  43. package/src/core/apc/parser.js +12 -5
  44. package/src/core/apc/paths.js +87 -0
  45. package/src/core/apc/scaffold.js +82 -76
  46. package/src/core/apc/skill-sync.js +10 -0
  47. package/src/{host/daemon/plugins → core/channels}/telegram/dispatch.js +38 -16
  48. package/src/core/config/index.js +24 -2
  49. package/src/core/config/redact.js +95 -0
  50. package/src/core/constants/channels.js +2 -0
  51. package/src/core/constants/code-modes.js +10 -0
  52. package/src/core/constants/index.js +1 -0
  53. package/src/core/deck/manifest.js +186 -0
  54. package/src/core/engines/catalog.js +83 -0
  55. package/src/core/{tools → http-tools}/browser.js +0 -1
  56. package/src/core/{tools → http-tools}/fetch.js +0 -1
  57. package/src/core/{tools → http-tools}/glob.js +0 -1
  58. package/src/core/{tools → http-tools}/grep.js +0 -1
  59. package/src/core/{tools → http-tools}/registry.js +0 -1
  60. package/src/core/{tools → http-tools}/search.js +0 -1
  61. package/src/core/i18n/en.js +9 -0
  62. package/src/core/i18n/es.js +12 -0
  63. package/src/core/i18n/index.js +54 -0
  64. package/src/core/i18n/pt.js +9 -0
  65. package/src/core/identity/telegram.js +2 -1
  66. package/src/core/mcp/runner.js +272 -14
  67. package/src/core/mcp/sources.js +3 -2
  68. package/src/core/routines/index.js +16 -0
  69. package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
  70. package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
  71. package/src/core/runtime-skills/apx/SKILL.md +83 -0
  72. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +125 -0
  73. package/src/core/runtime-skills/apx-agent/SKILL.md +97 -0
  74. package/src/core/runtime-skills/apx-mcp/SKILL.md +111 -0
  75. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +169 -0
  76. package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +20 -29
  77. package/src/core/runtime-skills/apx-routine/SKILL.md +127 -0
  78. package/src/core/runtime-skills/apx-runtime/SKILL.md +99 -0
  79. package/src/core/runtime-skills/apx-sessions/SKILL.md +232 -0
  80. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +129 -0
  81. package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +18 -21
  82. package/src/core/runtime-skills/apx-telegram/SKILL.md +120 -0
  83. package/src/core/runtime-skills/apx-voice/SKILL.md +117 -0
  84. package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
  85. package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
  86. package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
  87. package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
  88. package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
  89. package/src/core/stores/code-sessions.js +50 -2
  90. package/src/core/stores/routine-memory.js +1 -1
  91. package/src/core/stores/sessions-search.js +121 -0
  92. package/src/core/stores/sessions.js +38 -0
  93. package/src/core/vars/index.js +14 -0
  94. package/src/core/vars/interpolate.js +86 -0
  95. package/src/core/vars/sources.js +151 -0
  96. package/src/core/voice/audio-decode.js +38 -0
  97. package/src/core/voice/transcription.js +225 -0
  98. package/src/host/daemon/api/admin-config.js +5 -82
  99. package/src/host/daemon/api/agents.js +5 -5
  100. package/src/host/daemon/api/code.js +17 -169
  101. package/src/host/daemon/api/config.js +3 -4
  102. package/src/host/daemon/api/conversations.js +8 -29
  103. package/src/host/daemon/api/deck.js +37 -404
  104. package/src/host/daemon/api/engines.js +1 -80
  105. package/src/host/daemon/api/exec.js +1 -1
  106. package/src/host/daemon/api/mcps.js +32 -0
  107. package/src/host/daemon/api/routines.js +1 -1
  108. package/src/host/daemon/api/runtimes.js +4 -3
  109. package/src/host/daemon/api/sessions-search.js +24 -140
  110. package/src/host/daemon/api/sessions.js +12 -30
  111. package/src/host/daemon/api/shared.js +2 -1
  112. package/src/host/daemon/api/skills.js +140 -6
  113. package/src/host/daemon/api/super-agent.js +56 -1
  114. package/src/host/daemon/api/telegram.js +1 -11
  115. package/src/host/daemon/api/tools.js +6 -6
  116. package/src/host/daemon/api/transcribe.js +2 -2
  117. package/src/host/daemon/api/vars.js +137 -0
  118. package/src/host/daemon/api/voice.js +13 -290
  119. package/src/host/daemon/api.js +2 -0
  120. package/src/host/daemon/db.js +6 -6
  121. package/src/host/daemon/deck-exec.js +148 -0
  122. package/src/host/daemon/index.js +20 -3
  123. package/src/host/daemon/plugins/telegram/index.js +9 -9
  124. package/src/host/daemon/routines-scheduler.js +64 -0
  125. package/src/host/daemon/smoke.js +3 -2
  126. package/src/host/daemon/whisper-server.js +225 -0
  127. package/src/interfaces/cli/branding.js +53 -0
  128. package/src/interfaces/cli/commands/agent.js +3 -2
  129. package/src/interfaces/cli/commands/command.js +2 -3
  130. package/src/interfaces/cli/commands/messages.js +6 -2
  131. package/src/interfaces/cli/commands/pair.js +5 -4
  132. package/src/interfaces/cli/commands/search.js +1 -1
  133. package/src/interfaces/cli/commands/sessions.js +3 -2
  134. package/src/interfaces/cli/commands/skills.js +290 -55
  135. package/src/interfaces/cli/index.js +84 -2
  136. package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
  137. package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
  138. package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
  139. package/src/interfaces/web/dist/index.html +2 -2
  140. package/src/interfaces/web/package-lock.json +182 -182
  141. package/src/interfaces/web/src/components/ModelCombobox.tsx +2 -1
  142. package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
  143. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
  144. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +37 -4
  145. package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
  146. package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
  147. package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
  148. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
  149. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
  150. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
  151. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
  152. package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
  153. package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
  154. package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
  155. package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
  156. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
  157. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
  158. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +73 -4
  159. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
  160. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
  161. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
  162. package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
  163. package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
  164. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
  165. package/src/interfaces/web/src/constants/index.ts +1 -1
  166. package/src/interfaces/web/src/hooks/useChat.ts +19 -0
  167. package/src/interfaces/web/src/i18n/en.ts +175 -7
  168. package/src/interfaces/web/src/i18n/es.ts +180 -15
  169. package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
  170. package/src/interfaces/web/src/lib/api/skills.ts +70 -0
  171. package/src/interfaces/web/src/lib/api/vars.ts +38 -0
  172. package/src/interfaces/web/src/lib/api.ts +1 -0
  173. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
  174. package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
  175. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
  176. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
  177. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
  178. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
  179. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
  180. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
  181. package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
  182. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
  183. package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
  184. package/src/interfaces/web/src/types/daemon.ts +15 -0
  185. package/skills/apx-agency-agents/SKILL.md +0 -141
  186. package/skills/apx-agent/SKILL.md +0 -100
  187. package/skills/apx-mcp-builder/SKILL.md +0 -183
  188. package/skills/apx-routine/SKILL.md +0 -140
  189. package/skills/apx-runtime/SKILL.md +0 -117
  190. package/skills/apx-sessions/SKILL.md +0 -281
  191. package/skills/apx-skill-builder/SKILL.md +0 -153
  192. package/skills/apx-telegram/SKILL.md +0 -131
  193. package/skills/apx-voice/SKILL.md +0 -137
  194. package/src/core/agent/prompts/action-discipline.md +0 -24
  195. package/src/core/agent/prompts/super-agent-base.md +0 -42
  196. package/src/host/daemon/transcription.js +0 -538
  197. package/src/host/daemon/whisper-transcribe.py +0 -73
  198. package/src/interfaces/web/dist/assets/index-Aaiw8BZN.css +0 -1
  199. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js +0 -602
  200. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js.map +0 -1
  201. /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
  202. /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
  203. /package/src/{host/daemon/plugins → core/channels}/telegram/helpers.js +0 -0
  204. /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
  205. /package/src/core/{tools → http-tools}/index.js +0 -0
  206. /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
  207. /package/src/{host/daemon → core/stores}/conversations.js +0 -0
  208. /package/src/{host/daemon → core/util}/thinking.js +0 -0
@@ -9,6 +9,7 @@ import { VoiceProviderModal, type VoiceProviderSave } from "../../components/voi
9
9
  import { VoiceTestCard } from "../../components/voice/VoiceTestCard";
10
10
  import { VoiceSttCard } from "../../components/voice/VoiceSttCard";
11
11
  import { Voice, type TranscriptionConfig, type TtsMode, type VoiceTtsConfig } from "../../lib/api/voice";
12
+ import { t } from "../../i18n";
12
13
 
13
14
  // Voices module — configure TTS/STT providers, pick the default engine, and
14
15
  // test playback. TTS provider availability comes from the daemon
@@ -123,7 +124,7 @@ export function VoiceScreen() {
123
124
  <div className="grid gap-6 xl:grid-cols-2">
124
125
  {/* Left: TTS providers */}
125
126
  <Section
126
- title="Proveedores de voz (TTS)"
127
+ title={t("voice_screen.providers_title")}
127
128
  description="Motores de síntesis. El estado lo reporta el daemon en vivo. Elegí cuál usar por defecto."
128
129
  >
129
130
  {provLoading || cfgLoading ? (
@@ -148,12 +149,12 @@ export function VoiceScreen() {
148
149
 
149
150
  {/* Right: test + STT */}
150
151
  <div className="space-y-6">
151
- <Section title="Probar voz" description='Elegí con qué motor sintetizar y, si aplica, cómo querés que hable.'>
152
+ <Section title={t("voice_screen.test_title")} description='Elegí con qué motor sintetizar y, si aplica, cómo querés que hable.'>
152
153
  <VoiceTestCard engines={engines} defaultProvider={configuredProvider} mode={mode} />
153
154
  </Section>
154
155
 
155
156
  <Section
156
- title="Transcripción (STT)"
157
+ title={t("voice_screen.stt_title")}
157
158
  description="Motor de voz a texto que usan el deck, Telegram y la CLI al escuchar."
158
159
  >
159
160
  {cfgLoading ? <Loading /> : <VoiceSttCard config={transcriptionCfg} onPatch={patchStt} />}
@@ -128,7 +128,7 @@ export function AgentDetailScreen({ pid }: { pid: string }) {
128
128
  <Stat label="Heartbeats" value={myRoutines.length} icon={Heart} />
129
129
  </div>
130
130
  <div className="grid gap-3 sm:grid-cols-2">
131
- <Section title="Skills & tools" description="">
131
+ <Section title={t("agent_detail_extra.skills_title")} description="">
132
132
  <div className="flex flex-wrap gap-1">
133
133
  {a.skills?.map((s) => <Badge key={s} tone="info"><Sparkles size={10} /> {s}</Badge>)}
134
134
  {a.tools?.map((t) => <Badge key={t}><Wrench size={10} /> {t}</Badge>)}
@@ -1,18 +1,25 @@
1
+ import { useState } from "react";
2
+ import { useNavigate } from "react-router-dom";
1
3
  import useSWR from "swr";
4
+ import { RefreshCw, Trash2 } from "lucide-react";
2
5
  import { Projects } from "../../lib/api";
3
6
  import { Section } from "../../components/Section";
4
- import { Empty, Loading } from "../../components/ui";
7
+ import { Button, Dialog, Empty, Loading } from "../../components/ui";
5
8
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../components/ui/tabs";
6
9
  import { ConfigTabsEditor } from "../../components/config/ConfigTabsEditor";
7
10
  import { APC_PROJECT_SECTIONS, PROJECT_OVERRIDE_SECTIONS } from "../../components/config/project-config-sections";
8
11
  import { useToast } from "../../components/Toast";
12
+ import { useProject } from "../../hooks/useProjects";
9
13
  import { flattenObject } from "../../lib/config-values";
10
14
  import { isSecretMarker } from "../../lib/secrets";
11
15
  import { t } from "../../i18n";
12
16
 
13
17
  export function ConfigTab({ pid }: { pid: string }) {
14
18
  const toast = useToast();
19
+ const navigate = useNavigate();
20
+ const { project, mutate: mutateProject } = useProject(pid);
15
21
  const cfg = useSWR(`/projects/${pid}/config`, () => Projects.config.show(pid));
22
+ const isBase = String(pid) === "0";
16
23
 
17
24
  if (cfg.isLoading) return <Loading />;
18
25
  if (!cfg.data) return <Empty>{t("project.config.no_data")}</Empty>;
@@ -81,10 +88,134 @@ export function ConfigTab({ pid }: { pid: string }) {
81
88
  </TabsContent>
82
89
  </Tabs>
83
90
  </Section>
91
+
92
+ {!isBase && project ? (
93
+ <DangerZone
94
+ pid={pid}
95
+ label={project.name || project.path}
96
+ onRebuilt={() => cfg.mutate()}
97
+ onUnregistered={() => { mutateProject(); navigate("/"); }}
98
+ />
99
+ ) : null}
84
100
  </div>
85
101
  );
86
102
  }
87
103
 
104
+ function DangerZone({
105
+ pid,
106
+ label,
107
+ onRebuilt,
108
+ onUnregistered,
109
+ }: {
110
+ pid: string;
111
+ label: string;
112
+ onRebuilt: () => void;
113
+ onUnregistered: () => void;
114
+ }) {
115
+ const toast = useToast();
116
+ const [busy, setBusy] = useState<"rebuild" | "unregister" | null>(null);
117
+ const [confirm, setConfirm] = useState<"rebuild" | "unregister" | null>(null);
118
+
119
+ const runRebuild = async () => {
120
+ setBusy("rebuild");
121
+ try {
122
+ await Projects.rebuild(pid);
123
+ toast.success(t("project.rebuild_done"));
124
+ onRebuilt();
125
+ } catch (e) {
126
+ toast.error((e as Error).message);
127
+ } finally {
128
+ setBusy(null);
129
+ setConfirm(null);
130
+ }
131
+ };
132
+
133
+ const runUnregister = async () => {
134
+ setBusy("unregister");
135
+ try {
136
+ await Projects.remove(pid);
137
+ toast.success(t("project.unregistered"));
138
+ onUnregistered();
139
+ } catch (e) {
140
+ toast.error((e as Error).message);
141
+ } finally {
142
+ setBusy(null);
143
+ setConfirm(null);
144
+ }
145
+ };
146
+
147
+ return (
148
+ <>
149
+ <Section
150
+ title={t("project.danger.title")}
151
+ description={t("project.danger.subtitle")}
152
+ >
153
+ <div className="space-y-3">
154
+ <div className="flex items-start justify-between gap-3 rounded-md border border-border bg-muted/30 px-3 py-3">
155
+ <div className="min-w-0">
156
+ <div className="text-sm font-medium">{t("project.rebuild")}</div>
157
+ <div className="text-xs text-muted-fg">{t("project.danger.rebuild_desc")}</div>
158
+ </div>
159
+ <Button size="sm" variant="secondary" onClick={() => setConfirm("rebuild")}>
160
+ <RefreshCw size={13} /> {t("project.rebuild")}
161
+ </Button>
162
+ </div>
163
+
164
+ <div className="flex items-start justify-between gap-3 rounded-md border border-red-500/40 bg-red-500/5 px-3 py-3">
165
+ <div className="min-w-0">
166
+ <div className="text-sm font-medium">{t("admin.unregister")}</div>
167
+ <div className="text-xs text-muted-fg">{t("project.danger.unregister_desc")}</div>
168
+ </div>
169
+ <Button size="sm" variant="destructive" onClick={() => setConfirm("unregister")}>
170
+ <Trash2 size={13} /> {t("admin.unregister")}
171
+ </Button>
172
+ </div>
173
+ </div>
174
+ </Section>
175
+
176
+ <Dialog
177
+ open={confirm === "rebuild"}
178
+ onClose={() => (busy ? null : setConfirm(null))}
179
+ title={t("project.danger.rebuild_confirm_title")}
180
+ description={t("project.danger.rebuild_confirm_desc", { label })}
181
+ size="sm"
182
+ footer={
183
+ <>
184
+ <Button variant="ghost" onClick={() => setConfirm(null)} disabled={busy !== null}>
185
+ {t("common.cancel")}
186
+ </Button>
187
+ <Button variant="primary" onClick={runRebuild} loading={busy === "rebuild"}>
188
+ {t("project.rebuild")}
189
+ </Button>
190
+ </>
191
+ }
192
+ >
193
+ <p className="text-sm text-muted-fg">{t("project.danger.rebuild_long")}</p>
194
+ </Dialog>
195
+
196
+ <Dialog
197
+ open={confirm === "unregister"}
198
+ onClose={() => (busy ? null : setConfirm(null))}
199
+ title={t("project.danger.unregister_confirm_title")}
200
+ description={t("project.unregister_confirm", { label })}
201
+ size="sm"
202
+ footer={
203
+ <>
204
+ <Button variant="ghost" onClick={() => setConfirm(null)} disabled={busy !== null}>
205
+ {t("common.cancel")}
206
+ </Button>
207
+ <Button variant="destructive" onClick={runUnregister} loading={busy === "unregister"}>
208
+ {t("admin.unregister")}
209
+ </Button>
210
+ </>
211
+ }
212
+ >
213
+ <p className="text-sm text-muted-fg">{t("project.danger.unregister_long")}</p>
214
+ </Dialog>
215
+ </>
216
+ );
217
+ }
218
+
88
219
  function cleanSet(set: Record<string, unknown>) {
89
220
  const out: Record<string, unknown> = {};
90
221
  for (const [key, value] of Object.entries(flattenObject(set))) {