target-supabase-sdk 0.2.3 → 0.2.4

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 (155) hide show
  1. package/README.md +24 -18
  2. package/dist/browser.d.ts +11 -4
  3. package/dist/browser.d.ts.map +1 -1
  4. package/dist/browser.js +3 -3
  5. package/dist/chunks/{enable-log-persist-C7GJo_Nc.js → enable-log-persist-B8rg_wXG.js} +5 -6
  6. package/dist/chunks/enable-log-persist-B8rg_wXG.js.map +1 -0
  7. package/dist/chunks/{create-logger-DyH3mZ8p.js → list.api-Ab9v8yOg.js} +66 -57
  8. package/dist/chunks/list.api-Ab9v8yOg.js.map +1 -0
  9. package/dist/chunks/{word.interface-DLgRobKV.js → word.interface-B_fbVFOW.js} +1078 -97
  10. package/dist/chunks/word.interface-B_fbVFOW.js.map +1 -0
  11. package/dist/extraction/extraction.api.d.ts +117 -0
  12. package/dist/extraction/extraction.api.d.ts.map +1 -0
  13. package/dist/extraction/extraction.interface.d.ts +43 -0
  14. package/dist/extraction/extraction.interface.d.ts.map +1 -0
  15. package/dist/list/list.interface.d.ts +2 -2
  16. package/dist/list/list.interface.d.ts.map +1 -1
  17. package/dist/node/node-runtime.base.d.ts +13 -1
  18. package/dist/node/node-runtime.base.d.ts.map +1 -1
  19. package/dist/node/process/create-managed-child-processes.d.ts +12 -0
  20. package/dist/node/process/create-managed-child-processes.d.ts.map +1 -0
  21. package/dist/node/process/index.d.ts +3 -1
  22. package/dist/node/process/index.d.ts.map +1 -1
  23. package/dist/node/process/managed-child-processes.d.ts +15 -2
  24. package/dist/node/process/managed-child-processes.d.ts.map +1 -1
  25. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts +23 -0
  26. package/dist/node/runtime-state/create-service-runtime-state-store.d.ts.map +1 -0
  27. package/dist/node/runtime-state/index.d.ts +4 -0
  28. package/dist/node/runtime-state/index.d.ts.map +1 -0
  29. package/dist/node/runtime-state/service-runtime-state.types.d.ts +57 -0
  30. package/dist/node/runtime-state/service-runtime-state.types.d.ts.map +1 -0
  31. package/dist/node/service-guard/index.d.ts +9 -0
  32. package/dist/node/service-guard/index.d.ts.map +1 -0
  33. package/dist/node/service-guard/register-service-guard-runner.d.ts +9 -0
  34. package/dist/node/service-guard/register-service-guard-runner.d.ts.map +1 -0
  35. package/dist/node/service-guard/run-readiness-gate.d.ts +11 -0
  36. package/dist/node/service-guard/run-readiness-gate.d.ts.map +1 -0
  37. package/dist/node/service-guard/run-service-guard-tick.d.ts +7 -0
  38. package/dist/node/service-guard/run-service-guard-tick.d.ts.map +1 -0
  39. package/dist/node/service-guard/service-guard-node.d.ts +18 -0
  40. package/dist/node/service-guard/service-guard-node.d.ts.map +1 -0
  41. package/dist/node/service-guard/service-guard.interface.d.ts +58 -0
  42. package/dist/node/service-guard/service-guard.interface.d.ts.map +1 -0
  43. package/dist/node/service-guard/worker-spawn-cooldown.d.ts +4 -0
  44. package/dist/node/service-guard/worker-spawn-cooldown.d.ts.map +1 -0
  45. package/dist/node/service-host/index.d.ts +9 -0
  46. package/dist/node/service-host/index.d.ts.map +1 -0
  47. package/dist/node/service-host/registry-slot-guard-step.d.ts +21 -0
  48. package/dist/node/service-host/registry-slot-guard-step.d.ts.map +1 -0
  49. package/dist/node/service-host/service-host.d.ts +36 -0
  50. package/dist/node/service-host/service-host.d.ts.map +1 -0
  51. package/dist/node/service-host/single-process-service.d.ts +21 -0
  52. package/dist/node/service-host/single-process-service.d.ts.map +1 -0
  53. package/dist/node.d.ts +15 -2
  54. package/dist/node.d.ts.map +1 -1
  55. package/dist/node.js +2088 -1495
  56. package/dist/node.js.map +1 -1
  57. package/dist/preload.js +3 -3
  58. package/dist/service/config.api.d.ts +143 -0
  59. package/dist/service/config.api.d.ts.map +1 -0
  60. package/dist/service/config.interface.d.ts +22 -0
  61. package/dist/service/config.interface.d.ts.map +1 -0
  62. package/dist/service/index.d.ts +16 -17
  63. package/dist/service/index.d.ts.map +1 -1
  64. package/dist/service/registry-lifecycle.d.ts +43 -0
  65. package/dist/service/registry-lifecycle.d.ts.map +1 -0
  66. package/dist/service/registry.service.d.ts +94 -0
  67. package/dist/service/registry.service.d.ts.map +1 -0
  68. package/dist/service/service-bootstrap.d.ts +28 -0
  69. package/dist/service/service-bootstrap.d.ts.map +1 -0
  70. package/dist/service/service.api.d.ts +160 -0
  71. package/dist/service/service.api.d.ts.map +1 -1
  72. package/dist/service/service.interface.d.ts +32 -1
  73. package/dist/service/service.interface.d.ts.map +1 -1
  74. package/dist/shared/log/index.d.ts +4 -0
  75. package/dist/shared/log/index.d.ts.map +1 -1
  76. package/dist/shared/log/log-batch.d.ts +44 -0
  77. package/dist/shared/log/log-batch.d.ts.map +1 -0
  78. package/dist/shared/log/log-persist-coordinator.d.ts +37 -0
  79. package/dist/shared/log/log-persist-coordinator.d.ts.map +1 -0
  80. package/dist/shared/log/log-persist-flush.d.ts.map +1 -1
  81. package/dist/shared/log/log-persist.config.d.ts +0 -1
  82. package/dist/shared/log/log-persist.config.d.ts.map +1 -1
  83. package/dist/shared/log/log-persist.interface.d.ts +8 -0
  84. package/dist/shared/log/log-persist.interface.d.ts.map +1 -1
  85. package/dist/shared/utils/config-path.utils.d.ts +21 -0
  86. package/dist/shared/utils/config-path.utils.d.ts.map +1 -1
  87. package/dist/shared/utils/get-value-at-path.d.ts +3 -0
  88. package/dist/shared/utils/get-value-at-path.d.ts.map +1 -0
  89. package/dist/task/index.d.ts +2 -0
  90. package/dist/task/index.d.ts.map +1 -1
  91. package/dist/task/task-manager.d.ts +1 -1
  92. package/dist/task/task-manager.d.ts.map +1 -1
  93. package/dist/task/task-post-retry.api.d.ts +24 -0
  94. package/dist/task/task-post-retry.api.d.ts.map +1 -0
  95. package/dist/task/task-repo-context.d.ts +7 -1
  96. package/dist/task/task-repo-context.d.ts.map +1 -1
  97. package/dist/trigger/trigger-manager.d.ts +1 -1
  98. package/dist/trigger/trigger-manager.d.ts.map +1 -1
  99. package/dist/trigger/trigger-node.d.ts +1 -0
  100. package/dist/trigger/trigger-node.d.ts.map +1 -1
  101. package/dist/trigger/trigger.constant.d.ts +1 -1
  102. package/dist/trigger/trigger.constant.d.ts.map +1 -1
  103. package/dist/trigger/trigger.interface.d.ts +10 -0
  104. package/dist/trigger/trigger.interface.d.ts.map +1 -1
  105. package/package.json +4 -2
  106. package/src/browser.ts +98 -4
  107. package/src/extraction/extraction.api.ts +232 -0
  108. package/src/extraction/extraction.interface.ts +45 -0
  109. package/src/list/list.interface.ts +2 -2
  110. package/src/node/node-runtime.base.ts +37 -6
  111. package/src/node/process/create-managed-child-processes.ts +27 -0
  112. package/src/node/process/index.ts +4 -0
  113. package/src/node/process/managed-child-processes.ts +48 -15
  114. package/src/node/runtime-state/create-service-runtime-state-store.ts +125 -0
  115. package/src/node/runtime-state/index.ts +17 -0
  116. package/src/node/runtime-state/service-runtime-state.types.ts +64 -0
  117. package/src/node/service-guard/index.ts +17 -0
  118. package/src/node/service-guard/register-service-guard-runner.ts +64 -0
  119. package/src/node/service-guard/run-readiness-gate.ts +34 -0
  120. package/src/node/service-guard/run-service-guard-tick.ts +106 -0
  121. package/src/node/service-guard/service-guard-node.ts +52 -0
  122. package/src/node/service-guard/service-guard.interface.ts +64 -0
  123. package/src/node/service-guard/worker-spawn-cooldown.ts +13 -0
  124. package/src/node/service-host/index.ts +30 -0
  125. package/src/node/service-host/registry-slot-guard-step.ts +57 -0
  126. package/src/node/service-host/service-host.ts +168 -0
  127. package/src/node/service-host/single-process-service.ts +58 -0
  128. package/src/node.ts +69 -0
  129. package/src/service/config.api.ts +224 -0
  130. package/src/service/config.interface.ts +25 -0
  131. package/src/service/index.ts +74 -149
  132. package/src/service/registry-lifecycle.ts +144 -0
  133. package/src/service/registry.service.ts +564 -0
  134. package/src/service/service-bootstrap.ts +74 -0
  135. package/src/service/service.api.ts +13 -0
  136. package/src/service/service.interface.ts +36 -1
  137. package/src/shared/log/index.ts +13 -0
  138. package/src/shared/log/log-batch.ts +156 -0
  139. package/src/shared/log/log-persist-coordinator.ts +107 -0
  140. package/src/shared/log/log-persist-flush.ts +3 -3
  141. package/src/shared/log/log-persist.config.ts +0 -2
  142. package/src/shared/log/log-persist.interface.ts +10 -0
  143. package/src/shared/utils/config-path.utils.ts +35 -0
  144. package/src/shared/utils/get-value-at-path.ts +17 -0
  145. package/src/task/index.ts +2 -0
  146. package/src/task/task-manager.ts +10 -4
  147. package/src/task/task-post-retry.api.ts +61 -0
  148. package/src/task/task-repo-context.ts +8 -1
  149. package/src/trigger/trigger-manager.ts +4 -2
  150. package/src/trigger/trigger-node.ts +10 -4
  151. package/src/trigger/trigger.constant.ts +1 -1
  152. package/src/trigger/trigger.interface.ts +10 -0
  153. package/dist/chunks/create-logger-DyH3mZ8p.js.map +0 -1
  154. package/dist/chunks/enable-log-persist-C7GJo_Nc.js.map +0 -1
  155. package/dist/chunks/word.interface-DLgRobKV.js.map +0 -1
@@ -1,6 +1,305 @@
1
- import { B as BaseValidator, e as createTarget, E as validateWithSchema, d as createLogger, A as updateTargetDetails, g as generateResponse, f as deleteTarget, i as getTarget, y as scanTargetList, h as getPossibleTarget, j as getTargetList, o as isOptimisticLockError, c as OPTIMISTIC_LOCK_FAILED_MESSAGE, O as OPTIMISTIC_LOCK_ERROR_CODE, s as logManager } from './create-logger-DyH3mZ8p.js';
1
+ import { b as LOG_PERSIST_LOADER_KEY, G as validateWithSchema, k as getTarget, j as getPossibleTarget, i as generateResponse, E as updateTargetDetails, f as createLogger, g as createTarget, o as isCreateTargetAlreadyExistsError, A as scanTargetList, B as BaseValidator, h as deleteTarget, q as isOptimisticLockError, l as getTargetList, e as OPTIMISTIC_LOCK_FAILED_MESSAGE, O as OPTIMISTIC_LOCK_ERROR_CODE, u as logManager } from './list.api-Ab9v8yOg.js';
2
2
  import { z } from 'zod';
3
3
 
4
+ /**
5
+ * Read side of the log-persist pipeline: decode persisted `LogBatch` Lists into
6
+ * structured batches and flat entries. Pure and defensive — malformed rows are
7
+ * skipped rather than thrown. Mirrors the write side in `log-persist-flush.ts`.
8
+ */
9
+ const LANES = new Set(["fast", "medium", "slow"]);
10
+ function asRecord$1(value) {
11
+ return typeof value === "object" && value !== null ? value : null;
12
+ }
13
+ function asFiniteNumber$1(value) {
14
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
15
+ }
16
+ function asString(value) {
17
+ return typeof value === "string" ? value : null;
18
+ }
19
+ /** Parse `ListDetails.meta` (object or legacy JSON string) into typed batch meta, or null. */
20
+ function parseLogBatchMeta(rawMeta) {
21
+ let source;
22
+ if (typeof rawMeta === "string") {
23
+ try {
24
+ source = asRecord$1(JSON.parse(rawMeta));
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ else {
31
+ source = asRecord$1(rawMeta);
32
+ }
33
+ if (source == null) {
34
+ return null;
35
+ }
36
+ const service = asString(source.service);
37
+ const processName = asString(source.process);
38
+ const laneRaw = asString(source.lane);
39
+ const idempotencyKey = asString(source.idempotencyKey);
40
+ if (service == null || processName == null || laneRaw == null || !LANES.has(laneRaw) || idempotencyKey == null) {
41
+ return null;
42
+ }
43
+ return {
44
+ service,
45
+ process: processName,
46
+ lane: laneRaw,
47
+ pid: asFiniteNumber$1(source.pid) ?? 0,
48
+ count: asFiniteNumber$1(source.count) ?? 0,
49
+ from: asFiniteNumber$1(source.from),
50
+ to: asFiniteNumber$1(source.to),
51
+ flushedAt: asFiniteNumber$1(source.flushedAt) ?? 0,
52
+ idempotencyKey,
53
+ };
54
+ }
55
+ /** Structural guard for a persisted {@link LogEntry}. */
56
+ function isLogEntry(value) {
57
+ const record = asRecord$1(value);
58
+ return (record != null &&
59
+ typeof record.timestamp === "number" &&
60
+ typeof record.level === "string" &&
61
+ typeof record.message === "string" &&
62
+ typeof record.topic === "string" &&
63
+ typeof record.module === "string" &&
64
+ typeof record.traceId === "string");
65
+ }
66
+ /** Is this List a persisted log batch (by loaderKey)? */
67
+ function isLogBatchList(list) {
68
+ return list.details?.loaderKey === LOG_PERSIST_LOADER_KEY;
69
+ }
70
+ /**
71
+ * Decode a `List` row into a {@link DecodedLogBatch}. Returns null when the row
72
+ * is not a log batch or the meta/items are malformed.
73
+ */
74
+ function decodeLogBatch(list) {
75
+ if (!isLogBatchList(list)) {
76
+ return null;
77
+ }
78
+ const meta = parseLogBatchMeta(list.details?.meta);
79
+ if (meta == null) {
80
+ return null;
81
+ }
82
+ const items = Array.isArray(list.details?.items) ? list.details.items : [];
83
+ const entries = items.filter(isLogEntry);
84
+ return {
85
+ listId: list.id,
86
+ createdAt: list.created_at,
87
+ meta,
88
+ entries,
89
+ };
90
+ }
91
+ /** Decode many List rows, dropping any that are not valid log batches. */
92
+ function decodeLogBatchList(lists) {
93
+ const decoded = [];
94
+ for (const list of lists) {
95
+ const batch = decodeLogBatch(list);
96
+ if (batch != null) {
97
+ decoded.push(batch);
98
+ }
99
+ }
100
+ return decoded;
101
+ }
102
+ /** Flatten one batch into per-entry rows carrying the batch origin fields. */
103
+ function flattenLogBatch(batch) {
104
+ return batch.entries.map((entry) => ({
105
+ ...entry,
106
+ service: batch.meta.service,
107
+ process: batch.meta.process,
108
+ lane: batch.meta.lane,
109
+ pid: batch.meta.pid,
110
+ batchId: batch.meta.idempotencyKey,
111
+ }));
112
+ }
113
+ /** Flatten many batches into a single flat entry list. */
114
+ function flattenLogBatches(batches) {
115
+ const flat = [];
116
+ for (const batch of batches) {
117
+ flat.push(...flattenLogBatch(batch));
118
+ }
119
+ return flat;
120
+ }
121
+
122
+ var CategoryExtraction;
123
+ (function (CategoryExtraction) {
124
+ CategoryExtraction["EXTRACTION"] = "extraction";
125
+ })(CategoryExtraction || (CategoryExtraction = {}));
126
+
127
+ const targetIdSchema$2 = z.string().trim().min(1);
128
+ const loaderKeySchema = z.string().trim().min(1);
129
+ const postExtractionSchema = z.object({
130
+ name: z.string().trim().min(1),
131
+ /** Source Target id — for log analysis this is the producing Task id. */
132
+ sourceId: targetIdSchema$2,
133
+ loaderKey: loaderKeySchema,
134
+ meta: z.unknown().optional(),
135
+ objects: z.array(z.unknown()).min(1),
136
+ tagList: z.array(z.string()).optional().default([]),
137
+ extra: z.string().optional(),
138
+ });
139
+ const getExtractionSchema = z
140
+ .object({
141
+ id: targetIdSchema$2.optional(),
142
+ sourceId: targetIdSchema$2.optional(),
143
+ loaderKey: loaderKeySchema.optional(),
144
+ })
145
+ .refine((payload) => {
146
+ const hasId = payload.id != null && payload.id !== "";
147
+ const hasSource = payload.sourceId != null && payload.sourceId !== "";
148
+ if (hasId) {
149
+ return !hasSource;
150
+ }
151
+ return hasSource && payload.loaderKey != null && payload.loaderKey !== "";
152
+ }, { message: "Provide id, or both sourceId and loaderKey" });
153
+ const scanExtractionListSchema = z.object({
154
+ loaderKey: loaderKeySchema.optional(),
155
+ sourceId: targetIdSchema$2.optional(),
156
+ maxRows: z.number().int().min(1).max(500).optional(),
157
+ ascending: z.boolean().optional(),
158
+ });
159
+ const patchExtractionObjectsSchema = z.object({
160
+ id: targetIdSchema$2,
161
+ objects: z.array(z.unknown()).min(1),
162
+ meta: z.unknown().optional(),
163
+ expectedRevision: z.number().int().min(0).optional(),
164
+ });
165
+ const extractionCategoryFilter = {
166
+ field: "category",
167
+ operator: "eq",
168
+ value: CategoryExtraction.EXTRACTION,
169
+ };
170
+ function extractionRedundancyFilters(sourceId, loaderKey) {
171
+ return [
172
+ extractionCategoryFilter,
173
+ { field: "value", operator: "eq", value: sourceId },
174
+ { field: "details->>loaderKey", operator: "eq", value: loaderKey },
175
+ ];
176
+ }
177
+ function normalizeExtractionMeta(meta, patch) {
178
+ const base = meta != null && typeof meta === "object" && !Array.isArray(meta)
179
+ ? { ...meta }
180
+ : {};
181
+ if (patch != null && typeof patch === "object" && !Array.isArray(patch)) {
182
+ Object.assign(base, patch);
183
+ }
184
+ const revision = typeof base.revision === "number" && Number.isInteger(base.revision) ? base.revision : 0;
185
+ base.revision = revision;
186
+ base.updatedAt = new Date().toISOString();
187
+ return base;
188
+ }
189
+ /** Create an Extraction row for `(sourceId, loaderKey)`. Idempotent on redundancy key. */
190
+ const postExtraction = validateWithSchema(postExtractionSchema, "postExtractionSchema")(async (payload) => {
191
+ const logger = createLogger({ module: "postExtraction" });
192
+ const meta = normalizeExtractionMeta(payload.meta, { revision: 0 });
193
+ try {
194
+ return await createTarget({
195
+ payload,
196
+ checkRedundancyFilterList: extractionRedundancyFilters(payload.sourceId, payload.loaderKey),
197
+ createFn: () => ({
198
+ name: payload.name,
199
+ value: payload.sourceId,
200
+ category: CategoryExtraction.EXTRACTION,
201
+ tagList: payload.tagList,
202
+ extra: payload.extra,
203
+ details: {
204
+ manifestVersion: 0,
205
+ loaderKey: payload.loaderKey,
206
+ meta,
207
+ objects: payload.objects,
208
+ },
209
+ }),
210
+ });
211
+ }
212
+ catch (error) {
213
+ if (isCreateTargetAlreadyExistsError(error)) {
214
+ logger.warn("Extraction already exists for source + loaderKey", {
215
+ topic: "extraction",
216
+ data: { sourceId: payload.sourceId, loaderKey: payload.loaderKey },
217
+ });
218
+ throw error;
219
+ }
220
+ throw error;
221
+ }
222
+ });
223
+ /** Fetch one Extraction by row id, or by `(sourceId, loaderKey)`. */
224
+ const getExtraction = validateWithSchema(getExtractionSchema, "getExtractionSchema")(async (payload) => {
225
+ if (payload.id != null && payload.id !== "") {
226
+ const result = await getTarget({
227
+ id: payload.id,
228
+ filterList: [extractionCategoryFilter],
229
+ });
230
+ return {
231
+ ...result,
232
+ data: result.data,
233
+ };
234
+ }
235
+ const result = await getPossibleTarget({
236
+ filterList: extractionRedundancyFilters(payload.sourceId, payload.loaderKey),
237
+ });
238
+ if (result.data == null) {
239
+ return generateResponse.error("Extraction not found", undefined, "NOT_FOUND");
240
+ }
241
+ return {
242
+ ...result,
243
+ data: result.data,
244
+ };
245
+ });
246
+ /** Scan Extraction rows (newest first by default). */
247
+ const scanExtractionList = validateWithSchema(scanExtractionListSchema, "scanExtractionListSchema")(async (payload) => {
248
+ const filterList = [extractionCategoryFilter];
249
+ if (payload.loaderKey != null) {
250
+ filterList.push({ field: "details->>loaderKey", operator: "eq", value: payload.loaderKey });
251
+ }
252
+ if (payload.sourceId != null) {
253
+ filterList.push({ field: "value", operator: "eq", value: payload.sourceId });
254
+ }
255
+ return scanTargetList({
256
+ category: CategoryExtraction.EXTRACTION,
257
+ filterList,
258
+ maxRows: payload.maxRows ?? 100,
259
+ orderBy: { field: "created_at", ascending: payload.ascending ?? false },
260
+ });
261
+ });
262
+ /** Replace {@link ExtractionDetails.objects} and bump `meta.revision`. */
263
+ const patchExtractionObjects = validateWithSchema(patchExtractionObjectsSchema, "patchExtractionObjectsSchema")(async (payload) => {
264
+ const optimisticLockFilterList = [];
265
+ if (payload.expectedRevision != null) {
266
+ optimisticLockFilterList.push({
267
+ field: "details->meta->>revision",
268
+ operator: "eq",
269
+ value: String(payload.expectedRevision),
270
+ });
271
+ }
272
+ try {
273
+ const data = await updateTargetDetails({
274
+ id: payload.id,
275
+ optimisticLockFilterList,
276
+ updateFn: (current) => {
277
+ const currentMeta = current.meta != null && typeof current.meta === "object" && !Array.isArray(current.meta)
278
+ ? current.meta
279
+ : {};
280
+ const revision = typeof currentMeta.revision === "number" && Number.isInteger(currentMeta.revision)
281
+ ? currentMeta.revision + 1
282
+ : 1;
283
+ return {
284
+ ...current,
285
+ meta: normalizeExtractionMeta(current.meta, {
286
+ ...(payload.meta != null && typeof payload.meta === "object" && !Array.isArray(payload.meta)
287
+ ? payload.meta
288
+ : {}),
289
+ revision,
290
+ }),
291
+ objects: payload.objects,
292
+ };
293
+ },
294
+ });
295
+ return generateResponse.success(data);
296
+ }
297
+ catch (error) {
298
+ const message = error instanceof Error ? error.message : String(error);
299
+ return generateResponse.error(message, undefined, "PATCH_FAILED");
300
+ }
301
+ });
302
+
4
303
  var CategoryIdea;
5
304
  (function (CategoryIdea) {
6
305
  CategoryIdea["OPPORTUNITY"] = "opportunity";
@@ -902,10 +1201,22 @@ var ServiceLifecycleStatus;
902
1201
  ServiceLifecycleStatus["SUNSET"] = "SUNSET";
903
1202
  })(ServiceLifecycleStatus || (ServiceLifecycleStatus = {}));
904
1203
 
1204
+ var CategoryConfig;
1205
+ (function (CategoryConfig) {
1206
+ CategoryConfig["CONFIG"] = "config";
1207
+ })(CategoryConfig || (CategoryConfig = {}));
1208
+ /** Globally unique Config key for the declarative system service registry. */
1209
+ const TARGET_SYSTEM_REGISTRY_KEY = "target-system-registry";
1210
+
905
1211
  var CategoryService;
906
1212
  (function (CategoryService) {
907
1213
  CategoryService["SERVICE"] = "service";
908
1214
  })(CategoryService || (CategoryService = {}));
1215
+ var ServiceSlotStatus;
1216
+ (function (ServiceSlotStatus) {
1217
+ ServiceSlotStatus["EMPTY"] = "EMPTY";
1218
+ ServiceSlotStatus["ACTIVE"] = "ACTIVE";
1219
+ })(ServiceSlotStatus || (ServiceSlotStatus = {}));
909
1220
  var CategoryApi;
910
1221
  (function (CategoryApi) {
911
1222
  CategoryApi["API"] = "api";
@@ -918,6 +1229,169 @@ var ApiMethod;
918
1229
  ApiMethod["DELETE"] = "DELETE";
919
1230
  })(ApiMethod || (ApiMethod = {}));
920
1231
 
1232
+ const targetIdSchema$1 = z.string().trim().min(1);
1233
+ const getConfigSchema = z
1234
+ .object({
1235
+ id: targetIdSchema$1.optional(),
1236
+ value: z.string().trim().min(1).optional(),
1237
+ })
1238
+ .refine((payload) => {
1239
+ const hasId = payload.id != null && payload.id !== "";
1240
+ const hasValue = payload.value != null && payload.value !== "";
1241
+ return hasId !== hasValue;
1242
+ }, { message: "Provide exactly one of id or value" });
1243
+ /** One declarative EMPTY slot entry for seeding the system registry. */
1244
+ const systemRegistrySeedSlotSchema = z.object({
1245
+ serviceValue: z.string().trim().min(1),
1246
+ });
1247
+ const postSystemRegistryConfigSchema = z.object({
1248
+ /** When omitted, {@link DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS} is used. */
1249
+ slots: z.array(systemRegistrySeedSlotSchema).min(1).optional(),
1250
+ tagList: z.array(z.string()).optional().default([]),
1251
+ });
1252
+ /** Same payload shape as {@link postSystemRegistryConfig} — replaces slots with fresh EMPTY rows. */
1253
+ const resetSystemRegistryConfigSchema = postSystemRegistryConfigSchema;
1254
+ const DEFAULT_RESET_RETRY_ATTEMPTS = 5;
1255
+ const RESET_RETRY_DELAY_MS = 50;
1256
+ /** Default one EMPTY slot per known L3 service (override via payload or seed file). */
1257
+ const DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS = [
1258
+ { serviceValue: "log-service" },
1259
+ { serviceValue: "watch-service" },
1260
+ { serviceValue: "download-service" },
1261
+ { serviceValue: "storage-service" },
1262
+ ];
1263
+ const configCategoryFilter = {
1264
+ field: "category",
1265
+ operator: "eq",
1266
+ value: CategoryConfig.CONFIG,
1267
+ };
1268
+ function buildConfigLookupFilters(payload) {
1269
+ const filters = [configCategoryFilter];
1270
+ if (payload.id == null || payload.id === "") {
1271
+ filters.push({ field: "value", operator: "eq", value: payload.value });
1272
+ }
1273
+ return filters;
1274
+ }
1275
+ /** Build EMPTY {@link ServiceSlot} rows from seed entries (one slot per array item). */
1276
+ function buildEmptyServiceSlots(seedSlots) {
1277
+ return seedSlots.map(({ serviceValue }) => ({
1278
+ serviceValue,
1279
+ serviceId: null,
1280
+ status: ServiceSlotStatus.EMPTY,
1281
+ }));
1282
+ }
1283
+ function parseRegistryRevision$1(rawMeta) {
1284
+ const source = typeof rawMeta === "object" && rawMeta !== null ? rawMeta : null;
1285
+ const revision = source?.revision;
1286
+ return typeof revision === "number" && Number.isFinite(revision) ? revision : 0;
1287
+ }
1288
+ function lockOnRegistryRevision$1(revision) {
1289
+ return [{ field: "details->meta->>revision", operator: "eq", value: String(revision) }];
1290
+ }
1291
+ function sleep$2(ms) {
1292
+ return new Promise((resolve) => setTimeout(resolve, ms));
1293
+ }
1294
+ /** Build `ConfigDetails` for the globally unique system registry row. */
1295
+ function buildSystemRegistryConfigDetails(slots) {
1296
+ return {
1297
+ manifestVersion: 0,
1298
+ loaderKey: TARGET_SYSTEM_REGISTRY_KEY,
1299
+ meta: { revision: 0 },
1300
+ objects: [...slots],
1301
+ };
1302
+ }
1303
+ /** Fetch a Config by id or by {@link Config.value} key (`category=config`). */
1304
+ const getConfig = validateWithSchema(getConfigSchema, "getConfigSchema")(async (payload) => {
1305
+ const filterList = buildConfigLookupFilters(payload);
1306
+ if (payload.id != null && payload.id !== "") {
1307
+ const result = await getTarget({
1308
+ id: payload.id,
1309
+ filterList,
1310
+ });
1311
+ return {
1312
+ ...result,
1313
+ data: result.data,
1314
+ };
1315
+ }
1316
+ const result = await getPossibleTarget({
1317
+ filterList,
1318
+ });
1319
+ if (result.data == null) {
1320
+ return {
1321
+ ...result,
1322
+ data: undefined,
1323
+ };
1324
+ }
1325
+ return {
1326
+ ...result,
1327
+ data: result.data,
1328
+ };
1329
+ });
1330
+ /**
1331
+ * Insert the globally unique system registry Config (`category=config`,
1332
+ * `value=target-system-registry`). Rejects duplicates via `checkRedundancyFilterList`.
1333
+ */
1334
+ const postSystemRegistryConfig = validateWithSchema(postSystemRegistryConfigSchema, "postSystemRegistryConfigSchema")(async ({ slots, tagList }) => {
1335
+ const seedSlots = [...(slots ?? DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS)];
1336
+ const serviceSlots = buildEmptyServiceSlots(seedSlots);
1337
+ const details = buildSystemRegistryConfigDetails(serviceSlots);
1338
+ return createTarget({
1339
+ payload: { slots: seedSlots, tagList },
1340
+ checkRedundancyFilterList: [
1341
+ configCategoryFilter,
1342
+ { field: "value", operator: "eq", value: TARGET_SYSTEM_REGISTRY_KEY },
1343
+ ],
1344
+ createFn: () => ({
1345
+ name: TARGET_SYSTEM_REGISTRY_KEY,
1346
+ value: TARGET_SYSTEM_REGISTRY_KEY,
1347
+ category: CategoryConfig.CONFIG,
1348
+ tagList,
1349
+ details,
1350
+ }),
1351
+ });
1352
+ });
1353
+ /**
1354
+ * Replace the system registry slot layout with fresh EMPTY rows.
1355
+ * Creates the row when missing (same as {@link postSystemRegistryConfig}).
1356
+ * Clears ACTIVE slot bindings — use for dev recovery after crashes or layout changes.
1357
+ */
1358
+ const resetSystemRegistryConfig = validateWithSchema(resetSystemRegistryConfigSchema, "resetSystemRegistryConfigSchema")(async ({ slots, tagList }) => {
1359
+ const seedSlots = [...(slots ?? DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS)];
1360
+ const serviceSlots = buildEmptyServiceSlots(seedSlots);
1361
+ const existing = await getConfig({ value: TARGET_SYSTEM_REGISTRY_KEY });
1362
+ if (existing.data == null) {
1363
+ return postSystemRegistryConfig({ slots: seedSlots, tagList });
1364
+ }
1365
+ const configId = existing.data.id;
1366
+ for (let attempt = 1; attempt <= DEFAULT_RESET_RETRY_ATTEMPTS; attempt += 1) {
1367
+ try {
1368
+ const fresh = await getConfig({ id: configId });
1369
+ if (fresh.data == null) {
1370
+ throw new Error(`System registry config disappeared during reset (id=${configId})`);
1371
+ }
1372
+ const revision = parseRegistryRevision$1(fresh.data.details.meta);
1373
+ const updated = await updateTargetDetails({
1374
+ id: configId,
1375
+ optimisticLockFilterList: lockOnRegistryRevision$1(revision),
1376
+ updateFn: (details) => ({
1377
+ ...details,
1378
+ meta: { revision: revision + 1 },
1379
+ objects: serviceSlots,
1380
+ }),
1381
+ });
1382
+ return generateResponse.success(updated);
1383
+ }
1384
+ catch (error) {
1385
+ if (isOptimisticLockError(error) && attempt < DEFAULT_RESET_RETRY_ATTEMPTS) {
1386
+ await sleep$2(RESET_RETRY_DELAY_MS * attempt);
1387
+ continue;
1388
+ }
1389
+ throw error;
1390
+ }
1391
+ }
1392
+ throw new Error("[resetSystemRegistryConfig] Optimistic lock retries exhausted");
1393
+ });
1394
+
921
1395
  const targetIdSchema = z.string().trim().min(1);
922
1396
  const enumMemberSchema = z.object({
923
1397
  key: z.string().trim().min(1),
@@ -987,11 +1461,21 @@ const apiDetailsSchema = z.object({
987
1461
  manifestVersion: z.number().int().nonnegative(),
988
1462
  lifecycle: serviceLifecycleSchema,
989
1463
  });
1464
+ const serviceNodeSnapshotSchema = z.object({
1465
+ nodeId: z.string().trim().min(1),
1466
+ status: z.nativeEnum(NodeStatus),
1467
+ lastHeartBeat: z.number().int().nonnegative(),
1468
+ });
1469
+ const serviceRuntimeSchema = z.object({
1470
+ lastHeartBeat: z.number().int().nonnegative(),
1471
+ nodes: z.array(serviceNodeSnapshotSchema).default([]),
1472
+ });
990
1473
  const serviceDetailsSchema = z.object({
991
1474
  manifestVersion: z.number().int().nonnegative(),
992
1475
  apiKeys: z.array(z.string().trim().min(1)),
993
1476
  dependencies: z.array(z.string().trim().min(1)).default([]),
994
1477
  lifecycle: serviceLifecycleSchema,
1478
+ runtime: serviceRuntimeSchema.optional(),
995
1479
  });
996
1480
  const postApiSchema = z.object({
997
1481
  name: z.string().trim().min(1),
@@ -1039,7 +1523,7 @@ const serviceCategoryFilter = {
1039
1523
  operator: "eq",
1040
1524
  value: CategoryService.SERVICE,
1041
1525
  };
1042
- const SERVICE_LIFECYCLE_STATUS_FIELD$1 = "details->lifecycle->>status";
1526
+ const SERVICE_LIFECYCLE_STATUS_FIELD = "details->lifecycle->>status";
1043
1527
  function buildServiceLookupFilters(payload) {
1044
1528
  const filters = [serviceCategoryFilter];
1045
1529
  if (payload.id != null && payload.id !== "") ;
@@ -1048,7 +1532,7 @@ function buildServiceLookupFilters(payload) {
1048
1532
  }
1049
1533
  if (payload.lifecycleStatus != null) {
1050
1534
  filters.push({
1051
- field: SERVICE_LIFECYCLE_STATUS_FIELD$1,
1535
+ field: SERVICE_LIFECYCLE_STATUS_FIELD,
1052
1536
  operator: "eq",
1053
1537
  value: payload.lifecycleStatus,
1054
1538
  });
@@ -1137,125 +1621,563 @@ const postService = validateWithSchema(postServiceSchema, "postServiceSchema")(a
1137
1621
  });
1138
1622
  });
1139
1623
 
1140
- const DISCOVER_LIFECYCLE_STATUS = ServiceLifecycleStatus.ACTIVE;
1141
- const SERVICE_LIFECYCLE_STATUS_FIELD = "details->lifecycle->>status";
1142
- async function lookupServicePrimary(value) {
1143
- const response = await getService({ value, lifecycleStatus: DISCOVER_LIFECYCLE_STATUS });
1624
+ /**
1625
+ * System registry — declarative service capacity (`target-system-registry` Config)
1626
+ * and startup/shutdown slot claims (`registerService` / `unregisterService`).
1627
+ *
1628
+ * Data planes:
1629
+ * - Config `details.objects` — {@link ServiceSlot} desired layout (EMPTY / ACTIVE)
1630
+ * - Service rows — runtime instances; guard maintains {@link ServiceDetails.runtime}
1631
+ * - Slot release: graceful shutdown via {@link unregisterService}; monitor (later)
1632
+ * for crashed / ungraceful exits (stale `Service.details.runtime`)
1633
+ */
1634
+ const LOG_TOPIC_REGISTRY = "service-registry";
1635
+ const DEFAULT_REGISTER_RETRY_ATTEMPTS = 5;
1636
+ class ServiceRegistryError extends Error {
1637
+ code;
1638
+ constructor(message, code) {
1639
+ super(message);
1640
+ this.code = code;
1641
+ this.name = "ServiceRegistryError";
1642
+ }
1643
+ }
1644
+ function asRecord(value) {
1645
+ return typeof value === "object" && value !== null ? value : null;
1646
+ }
1647
+ function asFiniteNumber(value) {
1648
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1649
+ }
1650
+ function isServiceSlotStatus(value) {
1651
+ return value === ServiceSlotStatus.EMPTY || value === ServiceSlotStatus.ACTIVE;
1652
+ }
1653
+ /** Defensive decode of one {@link ServiceSlot} from Config `details.objects`. */
1654
+ function parseServiceSlot(value) {
1655
+ const source = asRecord(value);
1656
+ if (source == null) {
1657
+ return null;
1658
+ }
1659
+ const serviceValue = typeof source.serviceValue === "string" ? source.serviceValue : null;
1660
+ const status = source.status;
1661
+ if (serviceValue == null || !isServiceSlotStatus(status)) {
1662
+ return null;
1663
+ }
1664
+ let serviceId = null;
1665
+ if (source.serviceId != null) {
1666
+ if (typeof source.serviceId !== "string" || source.serviceId === "") {
1667
+ return null;
1668
+ }
1669
+ serviceId = source.serviceId;
1670
+ }
1671
+ if (status === ServiceSlotStatus.EMPTY) {
1672
+ serviceId = null;
1673
+ }
1674
+ else if (serviceId == null) {
1675
+ return null;
1676
+ }
1677
+ return { serviceValue, serviceId, status };
1678
+ }
1679
+ function parseServiceSlots(config) {
1680
+ const slots = [];
1681
+ for (const object of config.details.objects) {
1682
+ const slot = parseServiceSlot(object);
1683
+ if (slot != null) {
1684
+ slots.push(slot);
1685
+ }
1686
+ }
1687
+ return slots;
1688
+ }
1689
+ /** Parse `details.meta.revision` from the system registry Config (defaults to 0). */
1690
+ function parseRegistryRevision(rawMeta) {
1691
+ const source = asRecord(rawMeta);
1692
+ const revision = asFiniteNumber(source?.revision);
1693
+ return revision ?? 0;
1694
+ }
1695
+ function nextRegistryMeta(nextRevision) {
1696
+ return { revision: nextRevision };
1697
+ }
1698
+ function lockOnRegistryRevision(revision) {
1699
+ return [{ field: "details->meta->>revision", operator: "eq", value: String(revision) }];
1700
+ }
1701
+ function sleep$1(ms) {
1702
+ return new Promise((resolve) => setTimeout(resolve, ms));
1703
+ }
1704
+ async function loadSystemRegistryConfig() {
1705
+ const response = await getConfig({ value: TARGET_SYSTEM_REGISTRY_KEY });
1706
+ if (response.data == null) {
1707
+ throw new ServiceRegistryError(`System registry config not found (value=${TARGET_SYSTEM_REGISTRY_KEY})`, "REGISTRY_CONFIG_NOT_FOUND");
1708
+ }
1709
+ return response.data;
1710
+ }
1711
+ async function resolveServiceById(serviceId) {
1712
+ const response = await getService({ id: serviceId });
1144
1713
  return response.data ?? null;
1145
1714
  }
1146
- async function lookupServiceByScan(value) {
1147
- const { data } = await scanTargetList({
1148
- category: CategoryService.SERVICE,
1149
- orderBy: { field: "value", ascending: true },
1150
- maxRows: 1,
1151
- filterList: [
1152
- { field: "value", operator: "eq", value },
1153
- {
1154
- field: SERVICE_LIFECYCLE_STATUS_FIELD,
1155
- operator: "eq",
1156
- value: DISCOVER_LIFECYCLE_STATUS,
1157
- },
1158
- ],
1715
+ /**
1716
+ * Load the global system registry Config and resolve each ACTIVE slot's Service row.
1717
+ * Read-only — does not mutate slots or heartbeats.
1718
+ */
1719
+ async function getTargetSystemRegistry() {
1720
+ const config = await loadSystemRegistryConfig();
1721
+ const slots = parseServiceSlots(config);
1722
+ const views = await Promise.all(slots.map(async (slot) => {
1723
+ if (slot.serviceId == null) {
1724
+ return { slot, service: null };
1725
+ }
1726
+ const service = await resolveServiceById(slot.serviceId);
1727
+ return { slot, service };
1728
+ }));
1729
+ return { config, slots: views };
1730
+ }
1731
+ function findFirstEmptySlot(slots, serviceValue) {
1732
+ return slots.findIndex((slot) => slot.serviceValue === serviceValue && slot.status === ServiceSlotStatus.EMPTY);
1733
+ }
1734
+ function countSlotsForValue(slots, serviceValue) {
1735
+ let declared = 0;
1736
+ let active = 0;
1737
+ let empty = 0;
1738
+ for (const slot of slots) {
1739
+ if (slot.serviceValue !== serviceValue) {
1740
+ continue;
1741
+ }
1742
+ declared++;
1743
+ if (slot.status === ServiceSlotStatus.ACTIVE) {
1744
+ active++;
1745
+ }
1746
+ else if (slot.status === ServiceSlotStatus.EMPTY) {
1747
+ empty++;
1748
+ }
1749
+ }
1750
+ return { declared, active, empty };
1751
+ }
1752
+ /**
1753
+ * Preflight before `postService` — fail fast when registry capacity is full.
1754
+ * Prevents orphan Service rows and child process spawn when no slot is available.
1755
+ */
1756
+ async function assertRegistrySlotAvailable(serviceValue) {
1757
+ const config = await loadSystemRegistryConfig();
1758
+ const slots = parseServiceSlots(config);
1759
+ const counts = countSlotsForValue(slots, serviceValue);
1760
+ if (counts.declared === 0) {
1761
+ throw new ServiceRegistryError(`Service ${serviceValue} is not declared in system registry config`, "SERVICE_NOT_DECLARED");
1762
+ }
1763
+ if (counts.empty === 0) {
1764
+ throw new ServiceRegistryError(`No EMPTY slot for ${serviceValue} — declared=${counts.declared}, active=${counts.active}. Refusing startup.`, "SERVICE_SLOTS_FULL");
1765
+ }
1766
+ }
1767
+ /**
1768
+ * Runtime guard: this process's Service instance must still own an ACTIVE registry slot.
1769
+ * Supports N>1 replicas — checks whether `serviceId` appears in any ACTIVE slot for
1770
+ * `serviceValue`, not merely the first ACTIVE slot.
1771
+ */
1772
+ async function assertRegistrySlotOwner(input) {
1773
+ const config = await loadSystemRegistryConfig();
1774
+ const slots = parseServiceSlots(config);
1775
+ const ownsSlot = slots.some((slot) => slot.serviceValue === input.serviceValue &&
1776
+ slot.status === ServiceSlotStatus.ACTIVE &&
1777
+ slot.serviceId === input.serviceId);
1778
+ if (ownsSlot) {
1779
+ return;
1780
+ }
1781
+ const activeId = slots.find((slot) => slot.serviceValue === input.serviceValue &&
1782
+ slot.status === ServiceSlotStatus.ACTIVE &&
1783
+ slot.serviceId != null)?.serviceId;
1784
+ throw new ServiceRegistryError(`Registry slot for ${input.serviceValue} is not owned by ${input.serviceId} (active=${activeId ?? "none"})`, "REGISTRY_SLOT_LOST");
1785
+ }
1786
+ function isServiceValueDeclared(slots, serviceValue) {
1787
+ return slots.some((slot) => slot.serviceValue === serviceValue);
1788
+ }
1789
+ function claimSlot(slots, slotIndex, serviceId) {
1790
+ const next = [...slots];
1791
+ next[slotIndex] = {
1792
+ ...next[slotIndex],
1793
+ serviceId,
1794
+ status: ServiceSlotStatus.ACTIVE,
1795
+ };
1796
+ return next;
1797
+ }
1798
+ async function persistSlotClaim(params) {
1799
+ const { configId, revision, slots } = params;
1800
+ await updateTargetDetails({
1801
+ id: configId,
1802
+ optimisticLockFilterList: lockOnRegistryRevision(revision),
1803
+ updateFn: (details) => ({
1804
+ ...details,
1805
+ meta: nextRegistryMeta(revision + 1),
1806
+ objects: slots,
1807
+ }),
1159
1808
  });
1160
- return data?.[0] ?? null;
1161
1809
  }
1162
- async function resolveDiscoverFailureReason(value) {
1163
- const response = await getService({ value });
1164
- if (response.data == null) {
1165
- return "not-found";
1810
+ function releaseOwnedSlot(slots, serviceId) {
1811
+ const slotIndex = slots.findIndex((slot) => slot.serviceId === serviceId && slot.status === ServiceSlotStatus.ACTIVE);
1812
+ if (slotIndex < 0) {
1813
+ return null;
1166
1814
  }
1167
- return "not-available";
1815
+ const next = [...slots];
1816
+ next[slotIndex] = {
1817
+ ...next[slotIndex],
1818
+ serviceId: null,
1819
+ status: ServiceSlotStatus.EMPTY,
1820
+ };
1821
+ return next;
1168
1822
  }
1169
1823
  /**
1170
- * Discover a single service by {@link Service.value}.
1171
- * Only returns services with `lifecycle.status === ACTIVE` (filtered at query time).
1824
+ * Claim one EMPTY slot for a running Service instance (`EMPTY → ACTIVE` only).
1172
1825
  *
1173
- * Lookup: primary `getService` → fallback `scanTargetList` by value.
1826
+ * - Each startup should `postService` a **new** instance row; do not reuse prior Service ids.
1827
+ * - Declared capacity = count of {@link ServiceSlot} rows sharing `service.value`
1828
+ * - No idempotent skip — if all slots are ACTIVE (e.g. crashed prior instance), throws
1829
+ * `SERVICE_SLOTS_FULL` until monitor/ops releases the slot
1830
+ * - Does not write heartbeats; guard maintains {@link ServiceDetails.runtime}
1831
+ * - Graceful release: {@link unregisterService}; crash recovery: future monitor
1174
1832
  */
1175
- async function discoverService(input) {
1176
- const value = input.value.trim();
1833
+ async function registerService(input) {
1834
+ const { service } = input;
1835
+ const serviceValue = service.value;
1836
+ const maxAttempts = input.maxAttempts ?? DEFAULT_REGISTER_RETRY_ATTEMPTS;
1177
1837
  const logger = createLogger({
1178
- module: "discoverService",
1838
+ module: "registerService",
1179
1839
  traceId: input.traceId,
1180
- labels: { serviceValue: value },
1840
+ labels: { serviceValue, serviceId: service.id },
1841
+ });
1842
+ logger.info("开始认领系统 registry 槽位", {
1843
+ topic: LOG_TOPIC_REGISTRY,
1844
+ data: { serviceValue, serviceId: service.id },
1181
1845
  });
1182
- if (value === "") {
1183
- const message = "discoverService: value must not be empty";
1184
- logger.warn(message, { topic: "service", data: { value: input.value } });
1185
- return generateResponse.error(message, undefined, "SERVICE_VALUE_REQUIRED");
1846
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
1847
+ try {
1848
+ const config = await loadSystemRegistryConfig();
1849
+ const revision = parseRegistryRevision(config.details.meta);
1850
+ const slots = parseServiceSlots(config);
1851
+ if (!isServiceValueDeclared(slots, serviceValue)) {
1852
+ throw new ServiceRegistryError(`Service ${serviceValue} is not declared in system registry config`, "SERVICE_NOT_DECLARED");
1853
+ }
1854
+ const emptyIndex = findFirstEmptySlot(slots, serviceValue);
1855
+ if (emptyIndex < 0) {
1856
+ throw new ServiceRegistryError(`No EMPTY slot for ${serviceValue} — declared capacity is full`, "SERVICE_SLOTS_FULL");
1857
+ }
1858
+ const nextSlots = claimSlot(slots, emptyIndex, service.id);
1859
+ await persistSlotClaim({
1860
+ configId: config.id,
1861
+ revision,
1862
+ slots: nextSlots,
1863
+ });
1864
+ logger.info("槽位认领成功", {
1865
+ topic: LOG_TOPIC_REGISTRY,
1866
+ data: {
1867
+ serviceValue,
1868
+ serviceId: service.id,
1869
+ slotIndex: emptyIndex,
1870
+ attempt,
1871
+ revision: revision + 1,
1872
+ },
1873
+ });
1874
+ return;
1875
+ }
1876
+ catch (error) {
1877
+ if (error instanceof ServiceRegistryError) {
1878
+ logger.error("槽位认领被拒绝", {
1879
+ topic: LOG_TOPIC_REGISTRY,
1880
+ data: { serviceValue, serviceId: service.id, code: error.code, message: error.message },
1881
+ });
1882
+ throw error;
1883
+ }
1884
+ if (isOptimisticLockError(error) && attempt < maxAttempts) {
1885
+ logger.warn("registry 乐观锁冲突,重试", {
1886
+ topic: LOG_TOPIC_REGISTRY,
1887
+ data: { serviceValue, serviceId: service.id, attempt, maxAttempts },
1888
+ });
1889
+ await sleep$1(50 * attempt);
1890
+ continue;
1891
+ }
1892
+ const message = error instanceof Error ? error.message : String(error);
1893
+ logger.error("槽位认领失败", {
1894
+ topic: LOG_TOPIC_REGISTRY,
1895
+ data: { serviceValue, serviceId: service.id, attempt, message },
1896
+ });
1897
+ throw new ServiceRegistryError(message, "REGISTRY_UPDATE_FAILED");
1898
+ }
1186
1899
  }
1187
- try {
1188
- logger.info("开始发现服务", {
1189
- topic: "service",
1190
- data: { value, lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
1191
- });
1192
- let service = await lookupServicePrimary(value);
1193
- let source = "primary";
1194
- if (service == null) {
1195
- logger.warn("主路径未命中,尝试 catalog 扫描回退", {
1196
- topic: "service",
1197
- data: { value, step: "scan-fallback", lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
1900
+ throw new ServiceRegistryError(`Failed to register ${serviceValue} after ${maxAttempts} attempts`, "REGISTRY_UPDATE_FAILED");
1901
+ }
1902
+ /** Resolve the ACTIVE registry slot id for a declared `serviceValue`. */
1903
+ async function resolveActiveRegistryServiceId(serviceValue) {
1904
+ const registry = await getTargetSystemRegistry();
1905
+ for (const { slot } of registry.slots) {
1906
+ if (slot.serviceValue === serviceValue && slot.status === ServiceSlotStatus.ACTIVE && slot.serviceId != null) {
1907
+ return slot.serviceId;
1908
+ }
1909
+ }
1910
+ return null;
1911
+ }
1912
+ function nodeToServiceNodeSnapshot(node) {
1913
+ return {
1914
+ nodeId: node.id,
1915
+ status: node.details.status,
1916
+ lastHeartBeat: node.details.lastHeartBeat,
1917
+ };
1918
+ }
1919
+ /** Roll up Node liveness into `Service.details.runtime` (service guard only). */
1920
+ async function patchServiceRuntime(input) {
1921
+ const serviceId = input.serviceId ?? (await resolveActiveRegistryServiceId(input.serviceValue));
1922
+ if (serviceId == null) {
1923
+ return;
1924
+ }
1925
+ const nodes = input.nodes.map(nodeToServiceNodeSnapshot);
1926
+ await updateTargetDetails({
1927
+ id: serviceId,
1928
+ updateFn: (details) => ({
1929
+ ...details,
1930
+ runtime: {
1931
+ lastHeartBeat: input.lastHeartBeat,
1932
+ nodes,
1933
+ },
1934
+ }),
1935
+ });
1936
+ }
1937
+ /**
1938
+ * Claim a registry slot at L3 startup — propagates {@link ServiceRegistryError} (e.g. `SERVICE_SLOTS_FULL`).
1939
+ */
1940
+ async function registerServiceAtStartup(input) {
1941
+ await registerService(input);
1942
+ }
1943
+ /**
1944
+ * Release the ACTIVE slot owned by this Service instance (`ACTIVE → EMPTY` only).
1945
+ *
1946
+ * - Idempotent when no ACTIVE slot is bound to `service.id`
1947
+ * - Does not mutate the Service row or `details.runtime`
1948
+ * - Does not release slots owned by other instances
1949
+ */
1950
+ async function unregisterService(input) {
1951
+ const { service } = input;
1952
+ const serviceValue = service.value;
1953
+ const maxAttempts = input.maxAttempts ?? DEFAULT_REGISTER_RETRY_ATTEMPTS;
1954
+ const logger = createLogger({
1955
+ module: "unregisterService",
1956
+ traceId: input.traceId,
1957
+ labels: { serviceValue, serviceId: service.id },
1958
+ });
1959
+ logger.info("开始释放系统 registry 槽位", {
1960
+ topic: LOG_TOPIC_REGISTRY,
1961
+ data: { serviceValue, serviceId: service.id },
1962
+ });
1963
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
1964
+ try {
1965
+ const config = await loadSystemRegistryConfig();
1966
+ const revision = parseRegistryRevision(config.details.meta);
1967
+ const slots = parseServiceSlots(config);
1968
+ const nextSlots = releaseOwnedSlot(slots, service.id);
1969
+ if (nextSlots == null) {
1970
+ logger.info("无绑定槽位,跳过释放", {
1971
+ topic: LOG_TOPIC_REGISTRY,
1972
+ data: { serviceValue, serviceId: service.id, attempt },
1973
+ });
1974
+ return;
1975
+ }
1976
+ await persistSlotClaim({
1977
+ configId: config.id,
1978
+ revision,
1979
+ slots: nextSlots,
1980
+ });
1981
+ logger.info("槽位释放成功", {
1982
+ topic: LOG_TOPIC_REGISTRY,
1983
+ data: {
1984
+ serviceValue,
1985
+ serviceId: service.id,
1986
+ attempt,
1987
+ revision: revision + 1,
1988
+ },
1198
1989
  });
1199
- service = await lookupServiceByScan(value);
1200
- source = "scan";
1990
+ return;
1201
1991
  }
1202
- if (service == null) {
1203
- const reason = await resolveDiscoverFailureReason(value);
1204
- if (reason === "not-available") {
1205
- const message = `Service ${value} is not available (lifecycle is not ACTIVE)`;
1206
- logger.warn("服务已注册但不可用", {
1207
- topic: "service",
1208
- data: { value, step: "not-available", lifecycleStatus: DISCOVER_LIFECYCLE_STATUS },
1992
+ catch (error) {
1993
+ if (error instanceof ServiceRegistryError) {
1994
+ logger.error("槽位释放被拒绝", {
1995
+ topic: LOG_TOPIC_REGISTRY,
1996
+ data: { serviceValue, serviceId: service.id, code: error.code, message: error.message },
1997
+ });
1998
+ throw error;
1999
+ }
2000
+ if (isOptimisticLockError(error) && attempt < maxAttempts) {
2001
+ logger.warn("registry 乐观锁冲突,重试", {
2002
+ topic: LOG_TOPIC_REGISTRY,
2003
+ data: { serviceValue, serviceId: service.id, attempt, maxAttempts },
1209
2004
  });
1210
- return generateResponse.error(message, undefined, "SERVICE_NOT_AVAILABLE");
2005
+ await sleep$1(50 * attempt);
2006
+ continue;
1211
2007
  }
1212
- const message = `Service not found: ${value}`;
1213
- logger.error("服务未发现", {
1214
- topic: "service",
1215
- data: { value, step: "not-found", tried: ["primary", "scan"] },
2008
+ const message = error instanceof Error ? error.message : String(error);
2009
+ logger.error("槽位释放失败", {
2010
+ topic: LOG_TOPIC_REGISTRY,
2011
+ data: { serviceValue, serviceId: service.id, attempt, message },
1216
2012
  });
1217
- return generateResponse.error(message, undefined, "SERVICE_NOT_FOUND");
2013
+ throw new ServiceRegistryError(message, "REGISTRY_UPDATE_FAILED");
1218
2014
  }
1219
- logger.info("服务发现成功", {
1220
- topic: "service",
2015
+ }
2016
+ throw new ServiceRegistryError(`Failed to unregister ${serviceValue} after ${maxAttempts} attempts`, "REGISTRY_UPDATE_FAILED");
2017
+ }
2018
+ /**
2019
+ * Best-effort slot release for process shutdown — never throws.
2020
+ */
2021
+ async function unregisterServiceAtShutdown(input) {
2022
+ const logger = createLogger({
2023
+ module: "unregisterServiceAtShutdown",
2024
+ traceId: input.traceId,
2025
+ labels: { serviceValue: input.service.value, serviceId: input.service.id },
2026
+ });
2027
+ try {
2028
+ await unregisterService(input);
2029
+ }
2030
+ catch (error) {
2031
+ const message = error instanceof Error ? error.message : String(error);
2032
+ const code = error instanceof ServiceRegistryError ? error.code : undefined;
2033
+ logger.warn("shutdown 释放 registry 槽位失败(best-effort)", {
2034
+ topic: LOG_TOPIC_REGISTRY,
1221
2035
  data: {
1222
- value,
1223
- source,
1224
- serviceId: service.id,
1225
- lifecycleStatus: service.details.lifecycle.status,
1226
- apiKeyCount: service.details.apiKeys.length,
1227
- dependencyCount: service.details.dependencies.length,
2036
+ serviceValue: input.service.value,
2037
+ serviceId: input.service.id,
2038
+ code,
2039
+ message,
1228
2040
  },
1229
2041
  });
1230
- return generateResponse.success(service);
2042
+ }
2043
+ }
2044
+
2045
+ const LOG_TOPIC = "service-registry-lifecycle";
2046
+ const EMPTY_REGISTRY_SLOT_RUNTIME_STATE = {
2047
+ serviceId: null,
2048
+ serviceValue: null,
2049
+ slotOwned: null,
2050
+ lastSlotCheckAt: null,
2051
+ lastSlotCheckError: null,
2052
+ };
2053
+ function createClaimedRegistrySlotRuntimeState(service) {
2054
+ return {
2055
+ serviceId: service.id,
2056
+ serviceValue: service.value,
2057
+ slotOwned: true,
2058
+ lastSlotCheckAt: null,
2059
+ lastSlotCheckError: null,
2060
+ };
2061
+ }
2062
+ /**
2063
+ * Preflight → create Service instance → claim registry slot.
2064
+ * On register failure after `createInstance`, deletes the orphan Service row.
2065
+ */
2066
+ async function claimServiceRegistrySlot(input) {
2067
+ const logger = createLogger({
2068
+ module: "claimServiceRegistrySlot",
2069
+ traceId: input.traceId,
2070
+ labels: { serviceValue: input.serviceValue },
2071
+ });
2072
+ await assertRegistrySlotAvailable(input.serviceValue);
2073
+ const service = await input.createInstance();
2074
+ let registered = false;
2075
+ try {
2076
+ await registerServiceAtStartup({ service, traceId: input.traceId });
2077
+ registered = true;
1231
2078
  }
1232
2079
  catch (error) {
1233
- const message = error instanceof Error ? error.message : String(error);
1234
- logger.error("服务发现失败", {
1235
- topic: "service",
1236
- data: { value, message },
1237
- });
1238
- let service = null;
1239
- try {
1240
- service = await lookupServiceByScan(value);
1241
- }
1242
- catch (fallbackError) {
1243
- const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
1244
- logger.error("扫描回退失败", {
1245
- topic: "service",
1246
- data: { value, message: fallbackMessage },
2080
+ await deleteTarget({ id: service.id }).catch((deleteError) => {
2081
+ const message = deleteError instanceof Error ? deleteError.message : String(deleteError);
2082
+ logger.warn("Failed to delete orphan Service row after register failure", {
2083
+ topic: LOG_TOPIC,
2084
+ data: { serviceId: service.id, message },
1247
2085
  });
1248
- return generateResponse.error(message, undefined, "SERVICE_DISCOVER_FAILED");
1249
- }
1250
- if (service != null) {
1251
- logger.warn("主路径异常后扫描回退成功", {
1252
- topic: "service",
1253
- data: { value, serviceId: service.id, primaryError: message },
1254
- });
1255
- return generateResponse.success(service);
2086
+ });
2087
+ throw error;
2088
+ }
2089
+ logger.info("registry slot claimed", {
2090
+ topic: LOG_TOPIC,
2091
+ data: { serviceValue: service.value, serviceId: service.id, registered },
2092
+ });
2093
+ return {
2094
+ service,
2095
+ release: async () => {
2096
+ await unregisterServiceAtShutdown({ service, traceId: input.traceId });
2097
+ },
2098
+ abandon: async () => {
2099
+ await deleteTarget({ id: service.id }).catch(() => undefined);
2100
+ },
2101
+ };
2102
+ }
2103
+ /**
2104
+ * Runtime guard step for service supervisor loops.
2105
+ * Transient read failures soft-fail; confirmed slot loss returns `shouldShutdown: true`.
2106
+ */
2107
+ async function runRegistrySlotGuardCheck(input) {
2108
+ try {
2109
+ await assertRegistrySlotOwner(input);
2110
+ return { slotOwned: true, shouldShutdown: false };
2111
+ }
2112
+ catch (error) {
2113
+ if (error instanceof ServiceRegistryError && error.code === "REGISTRY_SLOT_LOST") {
2114
+ return {
2115
+ slotOwned: false,
2116
+ shouldShutdown: true,
2117
+ error: error.message,
2118
+ };
1256
2119
  }
1257
- return generateResponse.error(message, undefined, "SERVICE_DISCOVER_FAILED");
2120
+ const message = error instanceof Error ? error.message : String(error);
2121
+ return {
2122
+ slotOwned: null,
2123
+ shouldShutdown: false,
2124
+ error: message,
2125
+ };
2126
+ }
2127
+ }
2128
+ function registrySlotRuntimePatchFromGuardResult(result, checkedAt) {
2129
+ return {
2130
+ slotOwned: result.slotOwned,
2131
+ lastSlotCheckAt: checkedAt,
2132
+ lastSlotCheckError: result.error ?? null,
2133
+ };
2134
+ }
2135
+
2136
+ function formatLocalDateYmd(date = new Date()) {
2137
+ const year = date.getFullYear();
2138
+ const month = String(date.getMonth() + 1).padStart(2, "0");
2139
+ const day = String(date.getDate()).padStart(2, "0");
2140
+ return `${year}-${month}-${day}`;
2141
+ }
2142
+ /** Default ACTIVE lifecycle for a newly posted Service instance row. */
2143
+ function createActiveServiceLifecycle(activeSince) {
2144
+ return {
2145
+ status: ServiceLifecycleStatus.ACTIVE,
2146
+ activeSince: activeSince ?? formatLocalDateYmd(),
2147
+ deprecatedAt: null,
2148
+ sunsetAt: null,
2149
+ };
2150
+ }
2151
+ /** Standard L3 Service `details` — empty apiKeys, manifest v0, ACTIVE lifecycle. */
2152
+ function defaultL3ServiceDetails(options) {
2153
+ return {
2154
+ manifestVersion: 0,
2155
+ apiKeys: [],
2156
+ dependencies: options?.dependencies ?? [],
2157
+ lifecycle: createActiveServiceLifecycle(),
2158
+ };
2159
+ }
2160
+ /**
2161
+ * Post a new Service instance row (L3 blueprint).
2162
+ * Same `value` may exist on many rows; registry slot claim selects the live instance.
2163
+ */
2164
+ async function postServiceInstance(options) {
2165
+ const logger = options.logger ?? createLogger({ module: "service-bootstrap" });
2166
+ const logTopic = options.logTopic ?? "bootstrap";
2167
+ const result = await postService({
2168
+ name: options.name,
2169
+ value: options.value,
2170
+ tagList: options.tagList ?? [],
2171
+ details: defaultL3ServiceDetails({ dependencies: options.dependencies }),
2172
+ });
2173
+ if (!result.success || result.data == null) {
2174
+ throw new Error(result.error?.message ?? "postService failed");
1258
2175
  }
2176
+ logger.success("service instance created", {
2177
+ topic: logTopic,
2178
+ data: { value: options.value, serviceId: result.data.id },
2179
+ });
2180
+ return result.data;
1259
2181
  }
1260
2182
 
1261
2183
  const RETRYABLE_CAUSE_CODES = new Set([
@@ -1476,6 +2398,24 @@ async function fetchBinaryWithRetry(url, init, options) {
1476
2398
  return response.arrayBuffer();
1477
2399
  }
1478
2400
 
2401
+ /** Read a dotted path (e.g. `data.items`) from a parsed JSON value. */
2402
+ function getValueAtPath(value, path) {
2403
+ if (path == null || path.trim() === "") {
2404
+ return value;
2405
+ }
2406
+ let current = value;
2407
+ for (const segment of path.split(".")) {
2408
+ if (segment === "") {
2409
+ continue;
2410
+ }
2411
+ if (current == null || typeof current !== "object") {
2412
+ return undefined;
2413
+ }
2414
+ current = current[segment];
2415
+ }
2416
+ return current;
2417
+ }
2418
+
1479
2419
  function fileBaseName(raw) {
1480
2420
  const normalized = raw.replace(/\\/g, "/");
1481
2421
  const parts = normalized.split("/");
@@ -1950,6 +2890,47 @@ const postTask = validateWithSchema(postTaskSchema, "postTaskSchema")(async ({ n
1950
2890
  return createTaskRow({ name, value, params, taskStatus, tagList, extra, traceParentId, taskTraceId }, logger);
1951
2891
  });
1952
2892
 
2893
+ const POST_TASK_DEFAULT_MAX_ATTEMPTS = 3;
2894
+ /**
2895
+ * Retry wrapper for {@link postTask} — for schedule runners posting tasks over flaky network.
2896
+ * Logs warn on intermediate failures and critical when all attempts fail.
2897
+ */
2898
+ async function postTaskWithRetry(payload, options) {
2899
+ const maxAttempts = options.maxAttempts ?? POST_TASK_DEFAULT_MAX_ATTEMPTS;
2900
+ let lastError = "unknown error";
2901
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2902
+ const { data: task, error } = await postTask(payload);
2903
+ if (error == null && task != null) {
2904
+ return { ok: true, task };
2905
+ }
2906
+ lastError = error?.message ?? lastError;
2907
+ if (attempt < maxAttempts) {
2908
+ options.logger.warn("postTask failed, retrying", {
2909
+ topic: options.topic,
2910
+ data: {
2911
+ ...options.context,
2912
+ traceId: options.traceId,
2913
+ itemLabel: options.itemLabel,
2914
+ attempt,
2915
+ maxAttempts,
2916
+ error: lastError,
2917
+ },
2918
+ });
2919
+ }
2920
+ }
2921
+ options.logger.critical("postTask failed after retries — skip item this cycle", {
2922
+ topic: options.topic,
2923
+ data: {
2924
+ ...options.context,
2925
+ traceId: options.traceId,
2926
+ itemLabel: options.itemLabel,
2927
+ maxAttempts,
2928
+ error: lastError,
2929
+ },
2930
+ });
2931
+ return { ok: false };
2932
+ }
2933
+
1953
2934
  /** Count tasks of `taskType` grouped by each requested status. */
1954
2935
  function countTasksByType(tasks, taskType, statuses) {
1955
2936
  const filtered = tasks.filter((task) => task.value === taskType);
@@ -1969,5 +2950,5 @@ var CategoryWord;
1969
2950
  CategoryWord["WORD"] = "word";
1970
2951
  })(CategoryWord || (CategoryWord = {}));
1971
2952
 
1972
- export { patchNodeHeartBeatSchema as $, ApiMethod as A, getParcelSchema as B, CategoryIdea as C, getScanRemoteRepoValues as D, getScanRemoteRepoValuesSchema as E, getService as F, getServiceSchema as G, installChunkFetchRegistry as H, isHttpUrl as I, isLocalFilesystemPath as J, isOpaqueChunkUrl as K, isRetryableHttpStatus as L, Market as M, NodeStatus as N, parcelDetailsSchema as O, ParcelManager as P, parseProviderPrefixedUrl as Q, ResultCode as R, ServiceLifecycleStatus as S, TASK_REPO_USAGE as T, patchChangeNodeStatus as U, patchChangeNodeStatusSchema as V, patchChangeTaskStatus as W, patchChangeTaskStatusSchema as X, patchClaimTask as Y, patchClaimTaskSchema as Z, patchNodeHeartBeat as _, CategoryLink as a, patchStopNode as a0, patchStopNodeSchema as a1, patchTaskProgress as a2, patchTaskProgressSchema as a3, postApi as a4, postApiSchema as a5, postLinkCreate as a6, postParcel as a7, postParcelSchema as a8, postRegisterNode as a9, postRegisterNodeSchema as aa, postService as ab, postServiceSchema as ac, postTask as ad, postTaskSchema as ae, publishParcel as af, registerProviderChunkResolver as ag, requestHasBody as ah, resolveFetchUrl as ai, restoreParcel as aj, restoreParcelById as ak, sanitizeFileName as al, sanitizeParcelFileName as am, schemaDefinitionSchema as an, serviceDetailsSchema as ao, serviceLifecycleSchema as ap, sha256Hex as aq, summarizeTaskQueue as ar, getErrorMessage as as, LOG_TOPIC_TASK as at, CRITICAL_UNKNOWN_TASK_TRACE_ID as au, toError as av, createTaskRow as aw, CategoryNode as b, CategoryParcel as c, CategoryRepo as d, CategoryService as e, CategoryTask as f, CategoryWord as g, PostLinkValidator as h, TaskStatus as i, TaskStatusAction as j, apiDetailsSchema as k, classifyNetworkError as l, countTasksByType as m, createStorageProviderRegistry as n, createUploadTracker as o, deleteParcel as p, deleteParcelSchema as q, discoverService as r, evaluateBusyNodeLiveness as s, fetchBinaryWithRetry as t, fetchWithRetry as u, fieldDefinitionSchema as v, formatNetworkError as w, getApi as x, getApiSchema as y, getParcel as z };
1973
- //# sourceMappingURL=word.interface-DLgRobKV.js.map
2953
+ export { getConfigSchema as $, ApiMethod as A, createStorageProviderRegistry as B, CategoryConfig as C, DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS as D, EMPTY_REGISTRY_SLOT_RUNTIME_STATE as E, createUploadTracker as F, decodeLogBatch as G, decodeLogBatchList as H, defaultL3ServiceDetails as I, deleteParcel as J, deleteParcelSchema as K, evaluateBusyNodeLiveness as L, Market as M, NodeStatus as N, fetchBinaryWithRetry as O, POST_TASK_DEFAULT_MAX_ATTEMPTS as P, fetchWithRetry as Q, ResultCode as R, ServiceLifecycleStatus as S, TARGET_SYSTEM_REGISTRY_KEY as T, fieldDefinitionSchema as U, flattenLogBatch as V, flattenLogBatches as W, formatNetworkError as X, getApi as Y, getApiSchema as Z, getConfig as _, CategoryExtraction as a, resolveFetchUrl as a$, getExtraction as a0, getExtractionSchema as a1, getParcel as a2, getParcelSchema as a3, getScanRemoteRepoValues as a4, getScanRemoteRepoValuesSchema as a5, getService as a6, getServiceSchema as a7, getTargetSystemRegistry as a8, getValueAtPath as a9, patchTaskProgressSchema as aA, postApi as aB, postApiSchema as aC, postExtraction as aD, postExtractionSchema as aE, postLinkCreate as aF, postParcel as aG, postParcelSchema as aH, postRegisterNode as aI, postRegisterNodeSchema as aJ, postService as aK, postServiceInstance as aL, postServiceSchema as aM, postSystemRegistryConfig as aN, postSystemRegistryConfigSchema as aO, postTask as aP, postTaskSchema as aQ, postTaskWithRetry as aR, publishParcel as aS, registerProviderChunkResolver as aT, registerService as aU, registerServiceAtStartup as aV, registrySlotRuntimePatchFromGuardResult as aW, requestHasBody as aX, resetSystemRegistryConfig as aY, resetSystemRegistryConfigSchema as aZ, resolveActiveRegistryServiceId as a_, installChunkFetchRegistry as aa, isHttpUrl as ab, isLocalFilesystemPath as ac, isLogBatchList as ad, isLogEntry as ae, isOpaqueChunkUrl as af, isRetryableHttpStatus as ag, parcelDetailsSchema as ah, parseLogBatchMeta as ai, parseProviderPrefixedUrl as aj, parseServiceSlot as ak, parseServiceSlots as al, patchChangeNodeStatus as am, patchChangeNodeStatusSchema as an, patchChangeTaskStatus as ao, patchChangeTaskStatusSchema as ap, patchClaimTask as aq, patchClaimTaskSchema as ar, patchExtractionObjects as as, patchExtractionObjectsSchema as at, patchNodeHeartBeat as au, patchNodeHeartBeatSchema as av, patchServiceRuntime as aw, patchStopNode as ax, patchStopNodeSchema as ay, patchTaskProgress as az, CategoryIdea as b, restoreParcel as b0, restoreParcelById as b1, runRegistrySlotGuardCheck as b2, sanitizeFileName as b3, sanitizeParcelFileName as b4, scanExtractionList as b5, scanExtractionListSchema as b6, schemaDefinitionSchema as b7, serviceDetailsSchema as b8, serviceLifecycleSchema as b9, serviceNodeSnapshotSchema as ba, serviceRuntimeSchema as bb, sha256Hex as bc, summarizeTaskQueue as bd, systemRegistrySeedSlotSchema as be, unregisterService as bf, unregisterServiceAtShutdown as bg, getErrorMessage as bh, LOG_TOPIC_TASK as bi, CRITICAL_UNKNOWN_TASK_TRACE_ID as bj, toError as bk, createTaskRow as bl, CategoryLink as c, CategoryNode as d, CategoryParcel as e, CategoryRepo as f, CategoryService as g, CategoryTask as h, CategoryWord as i, ParcelManager as j, PostLinkValidator as k, ServiceRegistryError as l, ServiceSlotStatus as m, TASK_REPO_USAGE as n, TaskStatus as o, TaskStatusAction as p, apiDetailsSchema as q, assertRegistrySlotAvailable as r, assertRegistrySlotOwner as s, buildEmptyServiceSlots as t, buildSystemRegistryConfigDetails as u, claimServiceRegistrySlot as v, classifyNetworkError as w, countTasksByType as x, createActiveServiceLifecycle as y, createClaimedRegistrySlotRuntimeState as z };
2954
+ //# sourceMappingURL=word.interface-B_fbVFOW.js.map