@agent-native/dispatch 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/README.md +56 -3
  2. package/dist/actions/apply-dream-proposal.d.ts +3 -0
  3. package/dist/actions/apply-dream-proposal.d.ts.map +1 -0
  4. package/dist/actions/apply-dream-proposal.js +11 -0
  5. package/dist/actions/apply-dream-proposal.js.map +1 -0
  6. package/dist/actions/create-dream-report.d.ts +3 -0
  7. package/dist/actions/create-dream-report.d.ts.map +1 -0
  8. package/dist/actions/create-dream-report.js +67 -0
  9. package/dist/actions/create-dream-report.js.map +1 -0
  10. package/dist/actions/create-workspace-resource.js +3 -3
  11. package/dist/actions/create-workspace-resource.js.map +1 -1
  12. package/dist/actions/delete-workspace-resource.js +1 -1
  13. package/dist/actions/delete-workspace-resource.js.map +1 -1
  14. package/dist/actions/ensure-dream-job.d.ts +3 -0
  15. package/dist/actions/ensure-dream-job.d.ts.map +1 -0
  16. package/dist/actions/ensure-dream-job.js +73 -0
  17. package/dist/actions/ensure-dream-job.js.map +1 -0
  18. package/dist/actions/get-dream-settings.d.ts +3 -0
  19. package/dist/actions/get-dream-settings.d.ts.map +1 -0
  20. package/dist/actions/get-dream-settings.js +11 -0
  21. package/dist/actions/get-dream-settings.js.map +1 -0
  22. package/dist/actions/get-dream.d.ts +3 -0
  23. package/dist/actions/get-dream.d.ts.map +1 -0
  24. package/dist/actions/get-dream.js +13 -0
  25. package/dist/actions/get-dream.js.map +1 -0
  26. package/dist/actions/get-workspace-resource-effective-context.d.ts +3 -0
  27. package/dist/actions/get-workspace-resource-effective-context.d.ts.map +1 -0
  28. package/dist/actions/get-workspace-resource-effective-context.js +27 -0
  29. package/dist/actions/get-workspace-resource-effective-context.js.map +1 -0
  30. package/dist/actions/index.d.ts.map +1 -1
  31. package/dist/actions/index.js +30 -4
  32. package/dist/actions/index.js.map +1 -1
  33. package/dist/actions/list-dream-candidates.d.ts +3 -0
  34. package/dist/actions/list-dream-candidates.d.ts.map +1 -0
  35. package/dist/actions/list-dream-candidates.js +68 -0
  36. package/dist/actions/list-dream-candidates.js.map +1 -0
  37. package/dist/actions/list-dreams.d.ts +3 -0
  38. package/dist/actions/list-dreams.d.ts.map +1 -0
  39. package/dist/actions/list-dreams.js +17 -0
  40. package/dist/actions/list-dreams.js.map +1 -0
  41. package/dist/actions/list-workspace-resources-for-app.d.ts +3 -0
  42. package/dist/actions/list-workspace-resources-for-app.d.ts.map +1 -0
  43. package/dist/actions/list-workspace-resources-for-app.js +12 -0
  44. package/dist/actions/list-workspace-resources-for-app.js.map +1 -0
  45. package/dist/actions/list-workspace-resources.js +1 -1
  46. package/dist/actions/list-workspace-resources.js.map +1 -1
  47. package/dist/actions/navigate.d.ts +1 -0
  48. package/dist/actions/navigate.d.ts.map +1 -1
  49. package/dist/actions/navigate.js +2 -1
  50. package/dist/actions/navigate.js.map +1 -1
  51. package/dist/actions/preview-dream-proposal.d.ts +3 -0
  52. package/dist/actions/preview-dream-proposal.d.ts.map +1 -0
  53. package/dist/actions/preview-dream-proposal.js +13 -0
  54. package/dist/actions/preview-dream-proposal.js.map +1 -0
  55. package/dist/actions/preview-workspace-resource-change.d.ts +3 -0
  56. package/dist/actions/preview-workspace-resource-change.d.ts.map +1 -0
  57. package/dist/actions/preview-workspace-resource-change.js +24 -0
  58. package/dist/actions/preview-workspace-resource-change.js.map +1 -0
  59. package/dist/actions/reject-dream-proposal.d.ts +3 -0
  60. package/dist/actions/reject-dream-proposal.d.ts.map +1 -0
  61. package/dist/actions/reject-dream-proposal.js +12 -0
  62. package/dist/actions/reject-dream-proposal.js.map +1 -0
  63. package/dist/actions/restore-starter-workspace-resources.d.ts +3 -0
  64. package/dist/actions/restore-starter-workspace-resources.d.ts.map +1 -0
  65. package/dist/actions/restore-starter-workspace-resources.js +14 -0
  66. package/dist/actions/restore-starter-workspace-resources.js.map +1 -0
  67. package/dist/actions/send-code-agent-remote-command.d.ts +3 -0
  68. package/dist/actions/send-code-agent-remote-command.d.ts.map +1 -0
  69. package/dist/actions/send-code-agent-remote-command.js +53 -0
  70. package/dist/actions/send-code-agent-remote-command.js.map +1 -0
  71. package/dist/actions/set-dream-settings.d.ts +3 -0
  72. package/dist/actions/set-dream-settings.d.ts.map +1 -0
  73. package/dist/actions/set-dream-settings.js +41 -0
  74. package/dist/actions/set-dream-settings.js.map +1 -0
  75. package/dist/actions/start-workspace-app-creation.js +1 -1
  76. package/dist/actions/start-workspace-app-creation.js.map +1 -1
  77. package/dist/actions/update-workspace-resource.js +1 -1
  78. package/dist/actions/update-workspace-resource.js.map +1 -1
  79. package/dist/actions/view-screen.d.ts.map +1 -1
  80. package/dist/actions/view-screen.js +73 -2
  81. package/dist/actions/view-screen.js.map +1 -1
  82. package/dist/components/approval-value-block.d.ts +7 -0
  83. package/dist/components/approval-value-block.d.ts.map +1 -0
  84. package/dist/components/approval-value-block.js +22 -0
  85. package/dist/components/approval-value-block.js.map +1 -0
  86. package/dist/components/create-app-popover.d.ts.map +1 -1
  87. package/dist/components/create-app-popover.js +6 -5
  88. package/dist/components/create-app-popover.js.map +1 -1
  89. package/dist/components/layout/Layout.d.ts.map +1 -1
  90. package/dist/components/layout/Layout.js +8 -1
  91. package/dist/components/layout/Layout.js.map +1 -1
  92. package/dist/components/ui/chart.d.ts +1 -1
  93. package/dist/components/workspace-app-card.d.ts.map +1 -1
  94. package/dist/components/workspace-app-card.js +25 -4
  95. package/dist/components/workspace-app-card.js.map +1 -1
  96. package/dist/components/workspace-resource-effective-stack.d.ts +11 -0
  97. package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -0
  98. package/dist/components/workspace-resource-effective-stack.js +59 -0
  99. package/dist/components/workspace-resource-effective-stack.js.map +1 -0
  100. package/dist/components/workspace-resource-impact-preview.d.ts +9 -0
  101. package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -0
  102. package/dist/components/workspace-resource-impact-preview.js +39 -0
  103. package/dist/components/workspace-resource-impact-preview.js.map +1 -0
  104. package/dist/db/migrations.d.ts.map +1 -1
  105. package/dist/db/migrations.js +59 -0
  106. package/dist/db/migrations.js.map +1 -1
  107. package/dist/db/schema.d.ts +714 -0
  108. package/dist/db/schema.d.ts.map +1 -1
  109. package/dist/db/schema.js +44 -2
  110. package/dist/db/schema.js.map +1 -1
  111. package/dist/hooks/use-navigation-state.d.ts +3 -0
  112. package/dist/hooks/use-navigation-state.d.ts.map +1 -1
  113. package/dist/hooks/use-navigation-state.js +23 -3
  114. package/dist/hooks/use-navigation-state.js.map +1 -1
  115. package/dist/lib/utils.d.ts +2 -1
  116. package/dist/lib/utils.d.ts.map +1 -1
  117. package/dist/lib/utils.js +5 -1
  118. package/dist/lib/utils.js.map +1 -1
  119. package/dist/routes/index.d.ts.map +1 -1
  120. package/dist/routes/index.js +1 -0
  121. package/dist/routes/index.js.map +1 -1
  122. package/dist/routes/pages/approval.d.ts.map +1 -1
  123. package/dist/routes/pages/approval.js +4 -1
  124. package/dist/routes/pages/approval.js.map +1 -1
  125. package/dist/routes/pages/approvals.js +1 -1
  126. package/dist/routes/pages/approvals.js.map +1 -1
  127. package/dist/routes/pages/dream-settings.d.ts +34 -0
  128. package/dist/routes/pages/dream-settings.d.ts.map +1 -0
  129. package/dist/routes/pages/dream-settings.js +68 -0
  130. package/dist/routes/pages/dream-settings.js.map +1 -0
  131. package/dist/routes/pages/dreams.d.ts +5 -0
  132. package/dist/routes/pages/dreams.d.ts.map +1 -0
  133. package/dist/routes/pages/dreams.js +435 -0
  134. package/dist/routes/pages/dreams.js.map +1 -0
  135. package/dist/routes/pages/workspace.d.ts.map +1 -1
  136. package/dist/routes/pages/workspace.js +187 -35
  137. package/dist/routes/pages/workspace.js.map +1 -1
  138. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  139. package/dist/server/lib/app-creation-store.js +3 -2
  140. package/dist/server/lib/app-creation-store.js.map +1 -1
  141. package/dist/server/lib/dispatch-integrations.d.ts +1 -1
  142. package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
  143. package/dist/server/lib/dispatch-integrations.js +9 -4
  144. package/dist/server/lib/dispatch-integrations.js.map +1 -1
  145. package/dist/server/lib/dispatch-remote-commands.d.ts +83 -0
  146. package/dist/server/lib/dispatch-remote-commands.d.ts.map +1 -0
  147. package/dist/server/lib/dispatch-remote-commands.js +256 -0
  148. package/dist/server/lib/dispatch-remote-commands.js.map +1 -0
  149. package/dist/server/lib/dispatch-store.d.ts +26 -0
  150. package/dist/server/lib/dispatch-store.d.ts.map +1 -1
  151. package/dist/server/lib/dispatch-store.js +17 -1
  152. package/dist/server/lib/dispatch-store.js.map +1 -1
  153. package/dist/server/lib/dreams-store.d.ts +398 -0
  154. package/dist/server/lib/dreams-store.d.ts.map +1 -0
  155. package/dist/server/lib/dreams-store.js +2330 -0
  156. package/dist/server/lib/dreams-store.js.map +1 -0
  157. package/dist/server/lib/thread-debug-store.d.ts +2 -2
  158. package/dist/server/lib/vault-store.d.ts +1 -1
  159. package/dist/server/lib/workspace-resources-store.d.ts +181 -17
  160. package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
  161. package/dist/server/lib/workspace-resources-store.js +737 -108
  162. package/dist/server/lib/workspace-resources-store.js.map +1 -1
  163. package/dist/server/plugins/agent-chat.js +1 -1
  164. package/dist/server/plugins/agent-chat.js.map +1 -1
  165. package/dist/server/plugins/integrations.js +2 -2
  166. package/dist/server/plugins/integrations.js.map +1 -1
  167. package/package.json +4 -2
  168. package/src/actions/apply-dream-proposal.ts +12 -0
  169. package/src/actions/create-dream-report.ts +76 -0
  170. package/src/actions/create-workspace-resource.ts +3 -3
  171. package/src/actions/delete-workspace-resource.ts +1 -1
  172. package/src/actions/ensure-dream-job.ts +76 -0
  173. package/src/actions/get-dream-settings.ts +12 -0
  174. package/src/actions/get-dream.ts +14 -0
  175. package/src/actions/get-workspace-resource-effective-context.ts +34 -0
  176. package/src/actions/index.spec.ts +26 -0
  177. package/src/actions/index.ts +31 -4
  178. package/src/actions/list-dream-candidates.ts +77 -0
  179. package/src/actions/list-dreams.ts +17 -0
  180. package/src/actions/list-workspace-resources-for-app.ts +13 -0
  181. package/src/actions/list-workspace-resources.ts +1 -1
  182. package/src/actions/navigate.ts +2 -1
  183. package/src/actions/preview-dream-proposal.ts +14 -0
  184. package/src/actions/preview-workspace-resource-change.ts +25 -0
  185. package/src/actions/reject-dream-proposal.ts +12 -0
  186. package/src/actions/restore-starter-workspace-resources.ts +17 -0
  187. package/src/actions/send-code-agent-remote-command.ts +59 -0
  188. package/src/actions/set-dream-settings.spec.ts +81 -0
  189. package/src/actions/set-dream-settings.ts +44 -0
  190. package/src/actions/start-workspace-app-creation.ts +1 -1
  191. package/src/actions/update-workspace-resource.ts +1 -1
  192. package/src/actions/view-screen.ts +90 -2
  193. package/src/components/approval-value-block.spec.tsx +59 -0
  194. package/src/components/approval-value-block.tsx +33 -0
  195. package/src/components/create-app-popover.tsx +6 -5
  196. package/src/components/layout/Layout.tsx +8 -0
  197. package/src/components/workspace-app-card.tsx +166 -1
  198. package/src/components/workspace-resource-effective-stack.spec.tsx +125 -0
  199. package/src/components/workspace-resource-effective-stack.tsx +141 -0
  200. package/src/components/workspace-resource-impact-preview.spec.tsx +147 -0
  201. package/src/components/workspace-resource-impact-preview.tsx +116 -0
  202. package/src/db/migrations.spec.ts +79 -0
  203. package/src/db/migrations.ts +59 -0
  204. package/src/db/schema.ts +46 -2
  205. package/src/hooks/use-navigation-state.ts +24 -5
  206. package/src/lib/utils.ts +6 -1
  207. package/src/routes/index.ts +1 -0
  208. package/src/routes/pages/approval.tsx +14 -1
  209. package/src/routes/pages/approvals.tsx +1 -1
  210. package/src/routes/pages/dream-settings.spec.ts +130 -0
  211. package/src/routes/pages/dream-settings.ts +103 -0
  212. package/src/routes/pages/dreams.tsx +1828 -0
  213. package/src/routes/pages/workspace.tsx +577 -97
  214. package/src/server/lib/app-creation-store.ts +3 -2
  215. package/src/server/lib/dispatch-integrations.ts +10 -3
  216. package/src/server/lib/dispatch-remote-commands.spec.ts +167 -0
  217. package/src/server/lib/dispatch-remote-commands.ts +375 -0
  218. package/src/server/lib/dispatch-store.ts +37 -1
  219. package/src/server/lib/dreams-store.spec.ts +1492 -0
  220. package/src/server/lib/dreams-store.ts +3168 -0
  221. package/src/server/lib/workspace-resource-approval-lifecycle.spec.ts +226 -0
  222. package/src/server/lib/workspace-resources-store.spec.ts +1106 -0
  223. package/src/server/lib/workspace-resources-store.ts +1001 -134
  224. package/src/server/plugins/agent-chat.ts +1 -1
  225. package/src/server/plugins/integrations.ts +2 -2
  226. package/dist/actions/sync-workspace-resources-to-all.d.ts +0 -3
  227. package/dist/actions/sync-workspace-resources-to-all.d.ts.map +0 -1
  228. package/dist/actions/sync-workspace-resources-to-all.js +0 -9
  229. package/dist/actions/sync-workspace-resources-to-all.js.map +0 -1
  230. package/dist/actions/sync-workspace-resources-to-app.d.ts +0 -3
  231. package/dist/actions/sync-workspace-resources-to-app.d.ts.map +0 -1
  232. package/dist/actions/sync-workspace-resources-to-app.js +0 -11
  233. package/dist/actions/sync-workspace-resources-to-app.js.map +0 -1
  234. package/src/actions/sync-workspace-resources-to-all.ts +0 -10
  235. package/src/actions/sync-workspace-resources-to-app.ts +0 -12
@@ -46,6 +46,7 @@ export const dispatchRoutes: RouteConfig = [
46
46
  route("approval", "./pages/approval.js"),
47
47
  route("approvals", "./pages/approvals.js"),
48
48
  route("audit", "./pages/audit.js"),
49
+ route("dreams", "./pages/dreams.js"),
49
50
  route("thread-debug", "./pages/thread-debug.js"),
50
51
  route("team", "./pages/team.js"),
51
52
  route("extensions", "./pages/extensions._index.js"),
@@ -7,6 +7,10 @@ import {
7
7
  appPath,
8
8
  } from "@agent-native/core/client";
9
9
  import { toast } from "sonner";
10
+ import {
11
+ ApprovalValueBlock,
12
+ parseApprovalValue,
13
+ } from "@/components/approval-value-block";
10
14
  import { Button } from "@/components/ui/button";
11
15
  import { Badge } from "@/components/ui/badge";
12
16
  import { Skeleton } from "@/components/ui/skeleton";
@@ -168,10 +172,12 @@ export default function ApprovalPreviewRoute() {
168
172
  }
169
173
 
170
174
  const isPending = approval.status === "pending";
175
+ const beforeValue = parseApprovalValue(approval.beforeValue);
176
+ const afterValue = parseApprovalValue(approval.afterValue);
171
177
 
172
178
  return (
173
179
  <div className="flex min-h-screen items-start justify-center bg-background p-6">
174
- <div className="w-full max-w-md space-y-4">
180
+ <div className="w-full max-w-2xl space-y-4">
175
181
  <div className="rounded-2xl border bg-card p-5">
176
182
  <div className="flex items-start gap-3">
177
183
  <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl border bg-muted text-foreground">
@@ -224,6 +230,13 @@ export default function ApprovalPreviewRoute() {
224
230
  )}
225
231
  </div>
226
232
 
233
+ {(beforeValue !== null || afterValue !== null) && (
234
+ <div className="mt-4 grid gap-3 md:grid-cols-2">
235
+ <ApprovalValueBlock label="Before" value={beforeValue} />
236
+ <ApprovalValueBlock label="After" value={afterValue} />
237
+ </div>
238
+ )}
239
+
227
240
  {isPending && (
228
241
  <div className="mt-4 flex gap-2">
229
242
  <Button
@@ -58,7 +58,7 @@ export default function ApprovalsRoute() {
58
58
  </div>
59
59
  <div className="mt-1 text-xs text-muted-foreground">
60
60
  {hasOrg
61
- ? "Applies to saved destinations and dispatch settings today."
61
+ ? "Applies to saved destinations, shared dream proposals, All-app workspace resources, and dispatch settings."
62
62
  : "Requires a team workspace. Set one up on the Team page."}
63
63
  </div>
64
64
  </div>
@@ -0,0 +1,130 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ dreamSettingsToDraft,
4
+ dreamSettingsUpdateFromDraft,
5
+ splitSourceIds,
6
+ type DreamSettingsDraft,
7
+ } from "./dream-settings.js";
8
+
9
+ function draft(
10
+ overrides: Partial<DreamSettingsDraft> = {},
11
+ ): DreamSettingsDraft {
12
+ return {
13
+ enabled: true,
14
+ schedule: "0 9 * * 1",
15
+ sourceId: "all",
16
+ sourceIdsText: "",
17
+ allSources: true,
18
+ query: "",
19
+ limit: "8",
20
+ sourceTimeoutMs: "30000",
21
+ sourceConcurrency: "2",
22
+ sourceStartStaggerMs: "250",
23
+ threadConcurrency: "3",
24
+ threadTimeoutMs: "8000",
25
+ minCandidateCount: "1",
26
+ ...overrides,
27
+ };
28
+ }
29
+
30
+ describe("dream settings payload helpers", () => {
31
+ it("normalizes persisted settings into editable draft text", () => {
32
+ expect(
33
+ dreamSettingsToDraft({
34
+ enabled: true,
35
+ schedule: "0 8 * * 2",
36
+ sourceId: "selected",
37
+ sourceIds: ["mail", "calendar"],
38
+ allSources: false,
39
+ query: "memory",
40
+ limit: 12,
41
+ sourceTimeoutMs: 45000,
42
+ sourceConcurrency: 4,
43
+ sourceStartStaggerMs: 500,
44
+ threadConcurrency: 5,
45
+ threadTimeoutMs: 9000,
46
+ minCandidateCount: 2,
47
+ }),
48
+ ).toMatchObject({
49
+ enabled: true,
50
+ schedule: "0 8 * * 2",
51
+ sourceId: "selected",
52
+ sourceIdsText: "mail\ncalendar",
53
+ allSources: false,
54
+ query: "memory",
55
+ limit: "12",
56
+ sourceTimeoutMs: "45000",
57
+ sourceConcurrency: "4",
58
+ sourceStartStaggerMs: "500",
59
+ threadConcurrency: "5",
60
+ threadTimeoutMs: "9000",
61
+ minCandidateCount: "2",
62
+ });
63
+ });
64
+
65
+ it("splits explicit source ids from commas and newlines", () => {
66
+ expect(splitSourceIds(" mail\ncalendar, analytics ,, \nbrain ")).toEqual([
67
+ "mail",
68
+ "calendar",
69
+ "analytics",
70
+ "brain",
71
+ ]);
72
+ });
73
+
74
+ it("builds a save payload that clears source ids and query", () => {
75
+ expect(
76
+ dreamSettingsUpdateFromDraft(
77
+ draft({
78
+ enabled: false,
79
+ schedule: " 0 10 * * 3 ",
80
+ sourceId: " current ",
81
+ sourceIdsText: "",
82
+ allSources: false,
83
+ query: " ",
84
+ minCandidateCount: "0",
85
+ }),
86
+ ),
87
+ ).toMatchObject({
88
+ enabled: false,
89
+ schedule: "0 10 * * 3",
90
+ sourceId: "current",
91
+ sourceIds: [],
92
+ allSources: false,
93
+ query: "",
94
+ limit: 8,
95
+ sourceTimeoutMs: 30000,
96
+ sourceConcurrency: 2,
97
+ sourceStartStaggerMs: 250,
98
+ threadConcurrency: 3,
99
+ threadTimeoutMs: 8000,
100
+ minCandidateCount: 0,
101
+ });
102
+ });
103
+
104
+ it("falls back to all source scope and omits invalid numeric edits", () => {
105
+ expect(
106
+ dreamSettingsUpdateFromDraft(
107
+ draft({
108
+ sourceId: " ",
109
+ sourceIdsText: "mail\ncalendar",
110
+ limit: "not-a-number",
111
+ threadTimeoutMs: "",
112
+ }),
113
+ ),
114
+ ).toMatchObject({
115
+ sourceId: "all",
116
+ sourceIds: ["mail", "calendar"],
117
+ allSources: true,
118
+ });
119
+ expect(
120
+ dreamSettingsUpdateFromDraft(
121
+ draft({ limit: "not-a-number", threadTimeoutMs: "" }),
122
+ ),
123
+ ).not.toHaveProperty("limit");
124
+ expect(
125
+ dreamSettingsUpdateFromDraft(
126
+ draft({ limit: "not-a-number", threadTimeoutMs: "" }),
127
+ ),
128
+ ).not.toHaveProperty("threadTimeoutMs");
129
+ });
130
+ });
@@ -0,0 +1,103 @@
1
+ export interface DreamSettings {
2
+ enabled: boolean;
3
+ schedule: string;
4
+ sourceId: string;
5
+ sourceIds?: string[];
6
+ allSources: boolean;
7
+ query?: string | null;
8
+ limit: number;
9
+ sourceTimeoutMs: number;
10
+ sourceConcurrency?: number;
11
+ sourceStartStaggerMs?: number;
12
+ threadConcurrency?: number;
13
+ threadTimeoutMs?: number;
14
+ minCandidateCount: number;
15
+ }
16
+
17
+ export interface DreamSettingsDraft {
18
+ enabled: boolean;
19
+ schedule: string;
20
+ sourceId: string;
21
+ sourceIdsText: string;
22
+ allSources: boolean;
23
+ query: string;
24
+ limit: string;
25
+ sourceTimeoutMs: string;
26
+ sourceConcurrency: string;
27
+ sourceStartStaggerMs: string;
28
+ threadConcurrency: string;
29
+ threadTimeoutMs: string;
30
+ minCandidateCount: string;
31
+ }
32
+
33
+ export function dreamSettingsToDraft(
34
+ settings: DreamSettings | null | undefined,
35
+ ): DreamSettingsDraft {
36
+ return {
37
+ enabled: settings?.enabled ?? false,
38
+ schedule: settings?.schedule ?? "0 9 * * 1",
39
+ sourceId: settings?.sourceId ?? "all",
40
+ sourceIdsText: (settings?.sourceIds ?? []).join("\n"),
41
+ allSources: settings?.allSources ?? true,
42
+ query: settings?.query ?? "",
43
+ limit: String(settings?.limit ?? 8),
44
+ sourceTimeoutMs: String(settings?.sourceTimeoutMs ?? 30_000),
45
+ sourceConcurrency: String(settings?.sourceConcurrency ?? 2),
46
+ sourceStartStaggerMs: String(settings?.sourceStartStaggerMs ?? 250),
47
+ threadConcurrency: String(settings?.threadConcurrency ?? 3),
48
+ threadTimeoutMs: String(settings?.threadTimeoutMs ?? 8_000),
49
+ minCandidateCount: String(settings?.minCandidateCount ?? 1),
50
+ };
51
+ }
52
+
53
+ export function splitSourceIds(value: string): string[] {
54
+ return value
55
+ .split(/[\n,]/)
56
+ .map((item) => item.trim())
57
+ .filter(Boolean);
58
+ }
59
+
60
+ function numberOrUndefined(value: string): number | undefined {
61
+ const trimmed = value.trim();
62
+ if (!trimmed) return undefined;
63
+ const numeric = Number(trimmed);
64
+ return Number.isFinite(numeric) ? numeric : undefined;
65
+ }
66
+
67
+ export function dreamSettingsUpdateFromDraft(
68
+ draft: DreamSettingsDraft,
69
+ ): Partial<DreamSettings> {
70
+ const sourceIds = splitSourceIds(draft.sourceIdsText);
71
+ const update: Partial<DreamSettings> = {
72
+ enabled: draft.enabled,
73
+ schedule: draft.schedule.trim(),
74
+ sourceId: draft.sourceId.trim() || (draft.allSources ? "all" : "current"),
75
+ sourceIds,
76
+ allSources: draft.allSources,
77
+ query: draft.query.trim(),
78
+ };
79
+
80
+ const limit = numberOrUndefined(draft.limit);
81
+ if (limit !== undefined) update.limit = limit;
82
+ const sourceTimeoutMs = numberOrUndefined(draft.sourceTimeoutMs);
83
+ if (sourceTimeoutMs !== undefined) update.sourceTimeoutMs = sourceTimeoutMs;
84
+ const sourceConcurrency = numberOrUndefined(draft.sourceConcurrency);
85
+ if (sourceConcurrency !== undefined) {
86
+ update.sourceConcurrency = sourceConcurrency;
87
+ }
88
+ const sourceStartStaggerMs = numberOrUndefined(draft.sourceStartStaggerMs);
89
+ if (sourceStartStaggerMs !== undefined) {
90
+ update.sourceStartStaggerMs = sourceStartStaggerMs;
91
+ }
92
+ const threadConcurrency = numberOrUndefined(draft.threadConcurrency);
93
+ if (threadConcurrency !== undefined) {
94
+ update.threadConcurrency = threadConcurrency;
95
+ }
96
+ const threadTimeoutMs = numberOrUndefined(draft.threadTimeoutMs);
97
+ if (threadTimeoutMs !== undefined) update.threadTimeoutMs = threadTimeoutMs;
98
+ const minCandidateCount = numberOrUndefined(draft.minCandidateCount);
99
+ if (minCandidateCount !== undefined) {
100
+ update.minCandidateCount = minCandidateCount;
101
+ }
102
+ return update;
103
+ }