target-supabase-sdk 0.2.24 → 0.3.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 (81) hide show
  1. package/dist/browser.d.ts +3 -2
  2. package/dist/browser.d.ts.map +1 -1
  3. package/dist/browser.js +3 -2
  4. package/dist/browser.js.map +1 -1
  5. package/dist/chunks/{list.api-BzbTJBsM.js → config-BNxsVKR4.js} +163 -10
  6. package/dist/chunks/config-BNxsVKR4.js.map +1 -0
  7. package/dist/chunks/{enable-C7lFooTG.js → enable-CF77OsXr.js} +20 -238
  8. package/dist/chunks/enable-CF77OsXr.js.map +1 -0
  9. package/dist/chunks/{task-queue-C_nUaM2S.js → task-queue-BL-KwAGW.js} +39 -13
  10. package/dist/chunks/task-queue-BL-KwAGW.js.map +1 -0
  11. package/dist/node/{node-runtime.base.d.ts → base-node-runtime.d.ts} +4 -1
  12. package/dist/node/base-node-runtime.d.ts.map +1 -0
  13. package/dist/node/node-liveness.d.ts +2 -0
  14. package/dist/node/node-liveness.d.ts.map +1 -1
  15. package/dist/node/node-service-id.d.ts +3 -0
  16. package/dist/node/node-service-id.d.ts.map +1 -0
  17. package/dist/node/node.api.d.ts +9 -1
  18. package/dist/node/node.api.d.ts.map +1 -1
  19. package/dist/node/node.interface.d.ts +9 -2
  20. package/dist/node/node.interface.d.ts.map +1 -1
  21. package/dist/node/service-guard/run-service-guard-tick.d.ts.map +1 -1
  22. package/dist/node/service-guard/service-guard-node.d.ts +3 -1
  23. package/dist/node/service-guard/service-guard-node.d.ts.map +1 -1
  24. package/dist/node/service-host/service-host.d.ts.map +1 -1
  25. package/dist/node/service-host/single-process-service.d.ts.map +1 -1
  26. package/dist/node.d.ts +2 -2
  27. package/dist/node.d.ts.map +1 -1
  28. package/dist/node.js +244 -198
  29. package/dist/node.js.map +1 -1
  30. package/dist/preload.js +3 -3
  31. package/dist/service/service.interface.d.ts +2 -2
  32. package/dist/service/service.interface.d.ts.map +1 -1
  33. package/dist/shared/log/core/log-batch.d.ts +4 -4
  34. package/dist/shared/log/core/log-batch.d.ts.map +1 -1
  35. package/dist/shared/log/index.d.ts +2 -1
  36. package/dist/shared/log/index.d.ts.map +1 -1
  37. package/dist/shared/log/spool/collector.d.ts +1 -1
  38. package/dist/shared/log/spool/collector.d.ts.map +1 -1
  39. package/dist/shared/log/spool/file.d.ts +2 -8
  40. package/dist/shared/log/spool/file.d.ts.map +1 -1
  41. package/dist/shared/log/spool/writer.d.ts.map +1 -1
  42. package/dist/shared/log/upload/flush.d.ts.map +1 -1
  43. package/dist/shared/log/upload/interface.d.ts +3 -11
  44. package/dist/shared/log/upload/interface.d.ts.map +1 -1
  45. package/dist/task/task-node.d.ts +3 -1
  46. package/dist/task/task-node.d.ts.map +1 -1
  47. package/dist/trigger/trigger-manager.d.ts +1 -1
  48. package/dist/trigger/trigger-node.d.ts +3 -1
  49. package/dist/trigger/trigger-node.d.ts.map +1 -1
  50. package/dist/trigger/trigger.api.d.ts +10 -10
  51. package/package.json +1 -1
  52. package/src/browser.ts +4 -3
  53. package/src/node/{node-runtime.base.ts → base-node-runtime.ts} +11 -2
  54. package/src/node/node-liveness.ts +6 -1
  55. package/src/node/node-service-id.ts +12 -0
  56. package/src/node/node.api.ts +7 -5
  57. package/src/node/node.interface.ts +10 -2
  58. package/src/node/service-guard/run-service-guard-tick.ts +12 -6
  59. package/src/node/service-guard/service-guard-node.ts +6 -1
  60. package/src/node/service-host/service-host.ts +2 -1
  61. package/src/node/service-host/single-process-service.ts +3 -0
  62. package/src/node.ts +2 -2
  63. package/src/service/service.interface.ts +2 -2
  64. package/src/shared/log/README.md +2 -3
  65. package/src/shared/log/core/log-batch.ts +12 -10
  66. package/src/shared/log/index.ts +2 -1
  67. package/src/shared/log/spool/collector.ts +46 -20
  68. package/src/shared/log/spool/file.ts +12 -25
  69. package/src/shared/log/spool/writer.ts +2 -7
  70. package/src/shared/log/upload/flush.ts +23 -38
  71. package/src/shared/log/upload/interface.ts +3 -12
  72. package/src/task/task-node.ts +6 -1
  73. package/src/trigger/trigger-manager.ts +1 -1
  74. package/src/trigger/trigger-node.ts +6 -1
  75. package/dist/chunks/enable-C7lFooTG.js.map +0 -1
  76. package/dist/chunks/list.api-BzbTJBsM.js.map +0 -1
  77. package/dist/chunks/task-queue-C_nUaM2S.js.map +0 -1
  78. package/dist/node/node-runtime.base.d.ts.map +0 -1
  79. package/dist/shared/log/upload/batch-id.d.ts +0 -13
  80. package/dist/shared/log/upload/batch-id.d.ts.map +0 -1
  81. package/src/shared/log/upload/batch-id.ts +0 -43
package/dist/node.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { z } from 'zod';
2
- import { M as MAX_POLL_TARGET_LIST_SIZE, V as validateWithSchema, g as createLogger, z as pollTargetList, k as generateResponse, h as createTarget, K as supabase, w as logManager, X as createScope, d as LogLevel, Y as patchScope, J as scanTargetList, Z as withModule, l as getPossibleTarget, E as postTarget, q as isCreateTargetAlreadyExistsError, m as getTarget, Q as updateTarget, t as isOptimisticLockResponse, R as updateTargetDetails } from './chunks/list.api-BzbTJBsM.js';
3
- export { B as BaseValidator, C as CREATE_TARGET_ALREADY_EXISTS_MESSAGE, a as CategoryList, L as LOG_BATCH_LOADER_KEY, b as LOG_MIN_LEVEL_ENV_KEY, c as LOG_PERSIST_LOADER_KEY, e as MAX_TARGET_LIST_PAGE_SIZE, O as OPTIMISTIC_LOCK_ERROR_CODE, f as OPTIMISTIC_LOCK_FAILED_MESSAGE, P as PostListValidator, S as StatusCode, U as UPDATE_TARGET_NOT_FOUND_MESSAGE, i as deleteTarget, j as formatZodError, n as getTargetList, o as getTargetTotalCount, p as handleSupabaseError, r as isDevEnvironment, s as isOptimisticLockError, u as logDev, v as logDevGroup, x as logMinLevelFromEnv, y as patchTarget, A as postListCreate, D as postLogListCreate, F as postTargetPayloadSchema, G as queryFilterSchema, H as resolveLogMinLevel, I as safeParseWithSchema, N as targetDraftSchema, T as validateWith } from './chunks/list.api-BzbTJBsM.js';
4
- import { l as loadEnvFiles, b as readEnv, c as requireEnv, d as resolveLogSpoolSpawnEnvForLabel, e as resolveLogSpoolConfig, f as resolveLogSpoolRoot, g as resolveAllLogSpoolProcessRoles, h as logSpoolProcessDir, s as spoolLogger, i as parseLogSpoolBatchFilename, j as computeLogBatchIdempotencyKey, k as buildLogListDraft, n as postLogBatch, a as logSpoolEnabledFromEnv, o as logSpoolConfigFromEnv, L as LOG_SPOOL_SERVICE_ID_ENV, q as ensureLogSpoolFromEnv, t as shutdownLogSpoolFromEnv, u as getLogSpoolStats } from './chunks/enable-C7lFooTG.js';
5
- export { C as CLI_PROD_FLAG, S as SERVICE_ENV_PROFILE_ENV_KEY, w as SERVICE_ENV_PROFILE_PROD, x as buildLogSpoolSpawnEnv, y as envBool, z as envInt, A as envMs, B as envNumber, D as envPort, E as envProfileFromProcess, F as resolveDefaultEnvFiles, r as resolveProjectRootByPackageName, G as resolveProjectRootFromModule, v as validateLogSpoolPreloadEnv } from './chunks/enable-C7lFooTG.js';
2
+ import { M as MAX_POLL_TARGET_LIST_SIZE, V as validateWithSchema, f as createLogger, z as pollTargetList, k as generateResponse, g as createTarget, w as logManager, a3 as createScope, c as LogLevel, a4 as patchScope, K as supabase, a5 as readEnv, a6 as requireEnv, J as scanTargetList, a7 as withModule, Y as resolveLogSpoolConfig, a8 as parseLogSpoolBatchFilename, a2 as logSpoolConfigFromEnv, a0 as LOG_SPOOL_SERVICE_ID_ENV, l as getPossibleTarget, E as postTarget, q as isCreateTargetAlreadyExistsError, m as getTarget, Q as updateTarget, t as isOptimisticLockResponse, R as updateTargetDetails } from './chunks/config-BNxsVKR4.js';
3
+ export { B as BaseValidator, C as CREATE_TARGET_ALREADY_EXISTS_MESSAGE, a as CategoryList, L as LOG_BATCH_LIST_VALUE, b as LOG_MIN_LEVEL_ENV_KEY, d as MAX_TARGET_LIST_PAGE_SIZE, O as OPTIMISTIC_LOCK_ERROR_CODE, e as OPTIMISTIC_LOCK_FAILED_MESSAGE, P as PostListValidator, S as StatusCode, U as UPDATE_TARGET_NOT_FOUND_MESSAGE, h as deleteTarget, W as envBool, a9 as envInt, aa as envMs, ab as envNumber, ac as envPort, i as formatLogSpoolBatchTimestamp, j as formatZodError, n as getTargetList, o as getTargetTotalCount, p as handleSupabaseError, r as isDevEnvironment, s as isOptimisticLockError, u as logDev, v as logDevGroup, x as logMinLevelFromEnv, y as patchTarget, A as postListCreate, D as postLogListCreate, F as postTargetPayloadSchema, G as queryFilterSchema, H as resolveLogMinLevel, I as safeParseWithSchema, N as targetDraftSchema, T as validateWith } from './chunks/config-BNxsVKR4.js';
6
4
  import { randomBytes, createHash } from 'node:crypto';
5
+ import { bT as getErrorMessage, bU as LOG_TOPIC_NODE, bv as requireNodeServiceIdFromEnv, bd as postRegisterNode, aT as patchChangeNodeStatus, n as NodeStatus, b2 as patchStopNode, a$ as patchNodeHeartBeat, bN as sha256Hex, E as EMPTY_REGISTRY_SLOT_RUNTIME_STATE, bD as runRegistrySlotGuardCheck, br as registrySlotRuntimePatchFromGuardResult, c as CategoryNode, a8 as evaluateBusyNodeLiveness, aL as nodesForTaskLiveness, b1 as patchServiceRuntime, aE as isLogEntry, N as NodeKind, X as claimServiceRegistrySlot, q as ServiceRegistryError, ab as fetchWithRetry, aH as isRetryableHttpStatus, aa as fetchBinaryWithRetry, aG as isOpaqueChunkUrl, e as CategoryRepo, aA as isHttpUrl, az as isFeedValue, bV as isFeedIngestSource, bW as resolveFeedOriginalStorageProvider, a9 as feedLinkDedupFilters, B as buildFeedLinkDraft, b as CategoryLink, bX as buildFeedTagList, i as IDEA_IMAGE_TEMP_DIR, au as guessMediaMime, M as MEDIA_CONTENT_HASH_ALGORITHM, aF as isMediaValue, aK as mediaLinkDedupFilters, Q as buildMediaLinkDraft, R as ResultCode, bY as LOG_TOPIC_TASK, s as TASK_REPO_USAGE, ao as getScanRemoteRepoValues, aX as patchClaimTask, bZ as CRITICAL_UNKNOWN_TASK_TRACE_ID, aV as patchChangeTaskStatus, u as TaskStatusAction, b_ as toError, bl as postTaskSchema, b$ as createTaskRow, t as TaskStatus } from './chunks/task-queue-BL-KwAGW.js';
6
+ export { A as ApiMethod, C as CategoryConfig, a as CategoryExtraction, d as CategoryParcel, f as CategoryService, g as CategoryTask, D as DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS, c0 as FEED_INGEST_SOURCES, F as FEED_VALUES, I as IDEA_IMAGE_LINK_NAME, h as IDEA_IMAGE_TAG_RAW, j as IDEA_LINK_VALUE, L as LINK_MANIFEST_VERSION, k as LIST_MANIFEST_VERSION, l as MEDIA_CONTENT_HASH_PREFIX_LENGTH, m as MEDIA_VALUES, P as POST_TASK_DEFAULT_MAX_ATTEMPTS, o as ParcelManager, p as PostLinkValidator, S as ServiceLifecycleStatus, r as ServiceSlotStatus, T as TARGET_SYSTEM_REGISTRY_KEY, v as apiDetailsSchema, w as appendSystemRegistryEmptySlots, x as assertRegistrySlotAvailable, y as assertRegistrySlotOwner, z as buildEmptyServiceSlots, G as buildFeedLinkName, H as buildIdeaImageLinkDraft, J as buildIdeaLinkDraft, K as buildLinkTargetDraft, O as buildListTargetDraft, U as buildMediaNameFromLocator, V as buildReviewLinkDraft, W as buildSystemRegistryConfigDetails, Y as classifyNetworkError, Z as countTasksByType, _ as createActiveServiceLifecycle, $ as createClaimedRegistrySlotRuntimeState, a0 as createStorageProviderRegistry, a1 as createUploadTracker, a2 as decodeLogBatch, a3 as decodeLogBatchList, a4 as defaultL3ServiceDetails, a5 as deleteParcel, a6 as deleteParcelSchema, a7 as escapeIlikePattern, ac as fieldDefinitionSchema, ad as flattenLogBatch, ae as flattenLogBatches, af as formatNetworkError, ag as getApi, ah as getApiSchema, ai as getConfig, aj as getConfigSchema, ak as getExtraction, al as getExtractionSchema, am as getParcel, an as getParcelSchema, ap as getScanRemoteRepoValuesSchema, aq as getService, ar as getServiceSchema, as as getTargetSystemRegistry, at as getValueAtPath, av as ideaCreateSchema, aw as ideaLinkValueFilters, ax as ideaUpdateSchema, ay as installChunkFetchRegistry, aB as isIdeaImageLinkName, aC as isLocalFilesystemPath, aD as isLogBatchList, aI as linkDedupFilters, aJ as linkTargetDraftBuildInputSchema, aM as normalizeStringList, aN as parcelDetailsSchema, aO as parseIdeaOriginal, aP as parseLogBatchMeta, aQ as parseProviderPrefixedUrl, aR as parseServiceSlot, aS as parseServiceSlots, aU as patchChangeNodeStatusSchema, aW as patchChangeTaskStatusSchema, aY as patchClaimTaskSchema, aZ as patchExtractionObjects, a_ as patchExtractionObjectsSchema, b0 as patchNodeHeartBeatSchema, b3 as patchStopNodeSchema, b4 as patchTaskProgress, b5 as patchTaskProgressSchema, b6 as postApi, b7 as postApiSchema, b8 as postExtraction, b9 as postExtractionSchema, ba as postLinkCreate, bb as postParcel, bc as postParcelSchema, be as postRegisterNodeSchema, bf as postService, bg as postServiceInstance, bh as postServiceSchema, bi as postSystemRegistryConfig, bj as postSystemRegistryConfigSchema, bk as postTask, bm as postTaskWithRetry, bn as publishParcel, bo as registerProviderChunkResolver, bp as registerService, bq as registerServiceAtStartup, bs as releaseSystemRegistrySlots, bt as releaseSystemRegistrySlotsByServiceId, bu as requestHasBody, bw as resetSystemRegistryConfig, bx as resetSystemRegistryConfigSchema, by as resolveActiveRegistryServiceId, bz as resolveFetchUrl, bA as restoreParcel, bB as restoreParcelById, bC as reviewLinksForNameFilters, bE as sanitizeFileName, bF as sanitizeParcelFileName, bG as scanExtractionList, bH as scanExtractionListSchema, bI as schemaDefinitionSchema, bJ as serviceDetailsSchema, bK as serviceLifecycleSchema, bL as serviceNodeSnapshotSchema, bM as serviceRuntimeSchema, bO as summarizeTaskQueue, bP as systemRegistrySeedSlotSchema, bQ as toPostgrestTextArrayLiteral, bR as unregisterService, bS as unregisterServiceAtShutdown } from './chunks/task-queue-BL-KwAGW.js';
7
+ import { l as loadEnvFiles, b as resolveLogSpoolSpawnEnvForLabel, c as resolveLogSpoolRoot, d as resolveAllLogSpoolProcessRoles, e as logSpoolProcessDir, s as spoolLogger, f as buildLogListDraft, g as postLogBatch, a as logSpoolEnabledFromEnv, h as ensureLogSpoolFromEnv, i as shutdownLogSpoolFromEnv, j as getLogSpoolStats } from './chunks/enable-CF77OsXr.js';
8
+ export { C as CLI_PROD_FLAG, S as SERVICE_ENV_PROFILE_ENV_KEY, k as SERVICE_ENV_PROFILE_PROD, n as buildLogSpoolSpawnEnv, o as envProfileFromProcess, q as resolveDefaultEnvFiles, r as resolveProjectRootByPackageName, t as resolveProjectRootFromModule, v as validateLogSpoolPreloadEnv } from './chunks/enable-CF77OsXr.js';
7
9
  import { readFile, unlink, mkdir, writeFile, rename, access, stat, readdir, constants } from 'node:fs/promises';
8
10
  import { dirname, resolve, join, isAbsolute } from 'node:path';
9
- import { bK as sha256Hex, bQ as getErrorMessage, bR as LOG_TOPIC_NODE, bb as postRegisterNode, aR as patchChangeNodeStatus, N as NodeStatus, b0 as patchStopNode, aZ as patchNodeHeartBeat, E as EMPTY_REGISTRY_SLOT_RUNTIME_STATE, bA as runRegistrySlotGuardCheck, bp as registrySlotRuntimePatchFromGuardResult, c as CategoryNode, a7 as evaluateBusyNodeLiveness, a$ as patchServiceRuntime, aD as isLogEntry, W as claimServiceRegistrySlot, p as ServiceRegistryError, aa as fetchWithRetry, aG as isRetryableHttpStatus, a9 as fetchBinaryWithRetry, aF as isOpaqueChunkUrl, e as CategoryRepo, az as isHttpUrl, ay as isFeedValue, bS as isFeedIngestSource, bT as resolveFeedOriginalStorageProvider, a8 as feedLinkDedupFilters, z as buildFeedLinkDraft, b as CategoryLink, bU as buildFeedTagList, i as IDEA_IMAGE_TEMP_DIR, at as guessMediaMime, M as MEDIA_CONTENT_HASH_ALGORITHM, aE as isMediaValue, aJ as mediaLinkDedupFilters, O as buildMediaLinkDraft, R as ResultCode, bV as LOG_TOPIC_TASK, r as TASK_REPO_USAGE, an as getScanRemoteRepoValues, aV as patchClaimTask, bW as CRITICAL_UNKNOWN_TASK_TRACE_ID, aT as patchChangeTaskStatus, t as TaskStatusAction, bX as toError, bj as postTaskSchema, bY as createTaskRow, s as TaskStatus } from './chunks/task-queue-C_nUaM2S.js';
10
- export { A as ApiMethod, C as CategoryConfig, a as CategoryExtraction, d as CategoryParcel, f as CategoryService, g as CategoryTask, D as DEFAULT_SYSTEM_REGISTRY_SEED_SLOTS, bZ as FEED_INGEST_SOURCES, F as FEED_VALUES, I as IDEA_IMAGE_LINK_NAME, h as IDEA_IMAGE_TAG_RAW, j as IDEA_LINK_VALUE, L as LINK_MANIFEST_VERSION, k as LIST_MANIFEST_VERSION, l as MEDIA_CONTENT_HASH_PREFIX_LENGTH, m as MEDIA_VALUES, P as POST_TASK_DEFAULT_MAX_ATTEMPTS, n as ParcelManager, o as PostLinkValidator, S as ServiceLifecycleStatus, q as ServiceSlotStatus, T as TARGET_SYSTEM_REGISTRY_KEY, u as apiDetailsSchema, v as appendSystemRegistryEmptySlots, w as assertRegistrySlotAvailable, x as assertRegistrySlotOwner, y as buildEmptyServiceSlots, B as buildFeedLinkName, G as buildIdeaImageLinkDraft, H as buildIdeaLinkDraft, J as buildLinkTargetDraft, K as buildListTargetDraft, Q as buildMediaNameFromLocator, U as buildReviewLinkDraft, V as buildSystemRegistryConfigDetails, X as classifyNetworkError, Y as countTasksByType, Z as createActiveServiceLifecycle, _ as createClaimedRegistrySlotRuntimeState, $ as createStorageProviderRegistry, a0 as createUploadTracker, a1 as decodeLogBatch, a2 as decodeLogBatchList, a3 as defaultL3ServiceDetails, a4 as deleteParcel, a5 as deleteParcelSchema, a6 as escapeIlikePattern, ab as fieldDefinitionSchema, ac as flattenLogBatch, ad as flattenLogBatches, ae as formatNetworkError, af as getApi, ag as getApiSchema, ah as getConfig, ai as getConfigSchema, aj as getExtraction, ak as getExtractionSchema, al as getParcel, am as getParcelSchema, ao as getScanRemoteRepoValuesSchema, ap as getService, aq as getServiceSchema, ar as getTargetSystemRegistry, as as getValueAtPath, au as ideaCreateSchema, av as ideaLinkValueFilters, aw as ideaUpdateSchema, ax as installChunkFetchRegistry, aA as isIdeaImageLinkName, aB as isLocalFilesystemPath, aC as isLogBatchList, aH as linkDedupFilters, aI as linkTargetDraftBuildInputSchema, aK as normalizeStringList, aL as parcelDetailsSchema, aM as parseIdeaOriginal, aN as parseLogBatchMeta, aO as parseProviderPrefixedUrl, aP as parseServiceSlot, aQ as parseServiceSlots, aS as patchChangeNodeStatusSchema, aU as patchChangeTaskStatusSchema, aW as patchClaimTaskSchema, aX as patchExtractionObjects, aY as patchExtractionObjectsSchema, a_ as patchNodeHeartBeatSchema, b1 as patchStopNodeSchema, b2 as patchTaskProgress, b3 as patchTaskProgressSchema, b4 as postApi, b5 as postApiSchema, b6 as postExtraction, b7 as postExtractionSchema, b8 as postLinkCreate, b9 as postParcel, ba as postParcelSchema, bc as postRegisterNodeSchema, bd as postService, be as postServiceInstance, bf as postServiceSchema, bg as postSystemRegistryConfig, bh as postSystemRegistryConfigSchema, bi as postTask, bk as postTaskWithRetry, bl as publishParcel, bm as registerProviderChunkResolver, bn as registerService, bo as registerServiceAtStartup, bq as releaseSystemRegistrySlots, br as releaseSystemRegistrySlotsByServiceId, bs as requestHasBody, bt as resetSystemRegistryConfig, bu as resetSystemRegistryConfigSchema, bv as resolveActiveRegistryServiceId, bw as resolveFetchUrl, bx as restoreParcel, by as restoreParcelById, bz as reviewLinksForNameFilters, bB as sanitizeFileName, bC as sanitizeParcelFileName, bD as scanExtractionList, bE as scanExtractionListSchema, bF as schemaDefinitionSchema, bG as serviceDetailsSchema, bH as serviceLifecycleSchema, bI as serviceNodeSnapshotSchema, bJ as serviceRuntimeSchema, bL as summarizeTaskQueue, bM as systemRegistrySeedSlotSchema, bN as toPostgrestTextArrayLiteral, bO as unregisterService, bP as unregisterServiceAtShutdown } from './chunks/task-queue-C_nUaM2S.js';
11
11
  import { spawn } from 'node:child_process';
12
12
  import { ProxyAgent } from 'undici';
13
13
  import { tmpdir } from 'node:os';
@@ -86,173 +86,6 @@ const getPollCommandList = validateWithSchema(getPollCommandListSchema, "getPoll
86
86
  return generateResponse.success(dequeuedList);
87
87
  });
88
88
 
89
- /**
90
- * Load standard Supabase env vars and initialize the process-wide Supabase holder.
91
- *
92
- * Required: `SUPABASE_URL`, `SUPABASE_ANON_KEY`
93
- * Optional: `SUPABASE_NEED_AUTH_URL`, `SUPABASE_NEED_AUTH_ANON_KEY`
94
- */
95
- async function initSupabaseFromStandardEnv(options = {}) {
96
- const env = options.env ?? process.env;
97
- const loadEnv = options.loadEnv ?? true;
98
- if (loadEnv) {
99
- if (options.root == null || options.root === "") {
100
- throw new Error("initSupabaseFromStandardEnv: root is required when loadEnv is true");
101
- }
102
- loadEnvFiles(options.root, { env, afterLoad: options.afterLoadEnv });
103
- }
104
- await supabase.initialize({
105
- supabaseUrl: requireEnv("SUPABASE_URL", env),
106
- supabaseAnonKey: requireEnv("SUPABASE_ANON_KEY", env),
107
- supabaseNeedAuthUrl: readEnv("SUPABASE_NEED_AUTH_URL", env),
108
- supabaseNeedAuthAnonKey: readEnv("SUPABASE_NEED_AUTH_ANON_KEY", env),
109
- });
110
- }
111
-
112
- /**
113
- * Public base URL: `envKey` if set (trailing slash stripped), else `http://localhost:{port}`.
114
- */
115
- function publicBaseUrlFromEnv(port, options) {
116
- const configured = readEnv(options.envKey, options.env ?? process.env);
117
- if (configured != null) {
118
- return configured.replace(/\/$/, "");
119
- }
120
- return `http://localhost:${port}`;
121
- }
122
-
123
- /** Per-file write queue — serializes read-modify-write for a single JSON path within one process. */
124
- const writeChains = new Map();
125
- function withSerializedFileWrites(filePath, operation) {
126
- const previous = writeChains.get(filePath) ?? Promise.resolve();
127
- const next = previous.then(operation, operation);
128
- writeChains.set(filePath, next.then(() => undefined, () => undefined));
129
- return next;
130
- }
131
-
132
- function mergeWithNested(defaults, current, patch, nestedKeys) {
133
- const merged = {
134
- ...defaults,
135
- ...current,
136
- ...patch,
137
- };
138
- for (const key of nestedKeys) {
139
- const defaultNested = defaults[key];
140
- if (defaultNested != null && typeof defaultNested === "object") {
141
- merged[key] = {
142
- ...defaultNested,
143
- ...current?.[key],
144
- ...patch[key],
145
- };
146
- }
147
- }
148
- return merged;
149
- }
150
- async function atomicWriteJson(filePath, data) {
151
- await mkdir(dirname(filePath), { recursive: true });
152
- const content = `${JSON.stringify(data, null, 2)}\n`;
153
- JSON.parse(content);
154
- const tempPath = `${filePath}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
155
- try {
156
- await writeFile(tempPath, content, "utf8");
157
- await rename(tempPath, filePath);
158
- }
159
- catch (error) {
160
- await unlink(tempPath).catch(() => undefined);
161
- throw error;
162
- }
163
- }
164
- /** JSON file-backed state with optional nested key merge and atomic writes. */
165
- function createJsonFileStateStore(options) {
166
- const { filePath, defaultState, nestedKeys = [], updatedAtKey } = options;
167
- function touchUpdatedAt(state) {
168
- if (updatedAtKey == null) {
169
- return state;
170
- }
171
- return {
172
- ...state,
173
- [updatedAtKey]: new Date().toISOString(),
174
- };
175
- }
176
- async function readFromDisk() {
177
- try {
178
- const raw = await readFile(filePath, "utf8");
179
- const parsed = JSON.parse(raw);
180
- return mergeWithNested(defaultState, parsed, {}, nestedKeys);
181
- }
182
- catch (error) {
183
- if (error.code === "ENOENT") {
184
- return mergeWithNested(defaultState, {}, {}, nestedKeys);
185
- }
186
- if (error instanceof SyntaxError) {
187
- await unlink(filePath).catch(() => undefined);
188
- return mergeWithNested(defaultState, {}, {}, nestedKeys);
189
- }
190
- throw error;
191
- }
192
- }
193
- return {
194
- read() {
195
- return readFromDisk();
196
- },
197
- write(patch) {
198
- return withSerializedFileWrites(filePath, async () => {
199
- const current = await readFromDisk();
200
- const next = touchUpdatedAt(mergeWithNested(defaultState, current, patch, nestedKeys));
201
- await atomicWriteJson(filePath, next);
202
- return next;
203
- });
204
- },
205
- reset() {
206
- return withSerializedFileWrites(filePath, async () => {
207
- const next = touchUpdatedAt({ ...defaultState });
208
- await atomicWriteJson(filePath, next);
209
- return next;
210
- });
211
- },
212
- };
213
- }
214
-
215
- /** Copy a Node.js Buffer view to a standalone ArrayBuffer. */
216
- function nodeBufferToArrayBuffer(nodeBuffer) {
217
- return nodeBuffer.buffer.slice(nodeBuffer.byteOffset, nodeBuffer.byteOffset + nodeBuffer.byteLength);
218
- }
219
- /** Read a local file with basic validation and SHA-256 digest. */
220
- async function readAndVerifySourceFile(filePath, options = {}) {
221
- const absolutePath = resolve(filePath);
222
- const allowEmpty = options.allowEmpty === true;
223
- try {
224
- await access(absolutePath);
225
- }
226
- catch {
227
- throw new Error(`Source file not found: ${absolutePath}`);
228
- }
229
- const fileStat = await stat(absolutePath);
230
- if (!fileStat.isFile()) {
231
- throw new Error(`Source path is not a file: ${absolutePath}`);
232
- }
233
- if (!allowEmpty && fileStat.size <= 0) {
234
- throw new Error(`Source file is empty: ${absolutePath}`);
235
- }
236
- if (options.maxBytes != null && fileStat.size > options.maxBytes) {
237
- throw new Error(`Source file exceeds maxBytes (${fileStat.size} > ${options.maxBytes}): ${absolutePath}`);
238
- }
239
- const nodeBuffer = await readFile(absolutePath);
240
- const buffer = nodeBufferToArrayBuffer(nodeBuffer);
241
- if (buffer.byteLength !== fileStat.size) {
242
- throw new Error(`Source file size mismatch after read (${buffer.byteLength} !== ${fileStat.size}): ${absolutePath}`);
243
- }
244
- const digest = await sha256Hex(buffer);
245
- if (options.expectedSha256 != null && digest.toLowerCase() !== options.expectedSha256.toLowerCase()) {
246
- throw new Error(`Source file SHA-256 mismatch (expected ${options.expectedSha256}, got ${digest}): ${absolutePath}`);
247
- }
248
- return {
249
- absolutePath,
250
- buffer,
251
- size: buffer.byteLength,
252
- sha256: digest,
253
- };
254
- }
255
-
256
89
  const formatTimestamp = (timestamp) => {
257
90
  return new Intl.DateTimeFormat("zh-CN", {
258
91
  year: "numeric",
@@ -468,7 +301,12 @@ class BaseNodeRuntime {
468
301
  }
469
302
  logger.debug("開始向 Supabase 註冊節點", { topic: LOG_TOPIC_NODE });
470
303
  try {
471
- const { data, error } = await postRegisterNode({ traceId: this.startupTraceId });
304
+ const serviceId = requireNodeServiceIdFromEnv();
305
+ const { data, error } = await postRegisterNode({
306
+ serviceId,
307
+ kind: this.getNodeKind(),
308
+ traceId: this.startupTraceId,
309
+ });
472
310
  if (data == null || error) {
473
311
  throw error ?? new Error("postRegisterNode 失敗");
474
312
  }
@@ -765,6 +603,173 @@ class BaseNodeRuntime {
765
603
  }
766
604
  }
767
605
 
606
+ /**
607
+ * Load standard Supabase env vars and initialize the process-wide Supabase holder.
608
+ *
609
+ * Required: `SUPABASE_URL`, `SUPABASE_ANON_KEY`
610
+ * Optional: `SUPABASE_NEED_AUTH_URL`, `SUPABASE_NEED_AUTH_ANON_KEY`
611
+ */
612
+ async function initSupabaseFromStandardEnv(options = {}) {
613
+ const env = options.env ?? process.env;
614
+ const loadEnv = options.loadEnv ?? true;
615
+ if (loadEnv) {
616
+ if (options.root == null || options.root === "") {
617
+ throw new Error("initSupabaseFromStandardEnv: root is required when loadEnv is true");
618
+ }
619
+ loadEnvFiles(options.root, { env, afterLoad: options.afterLoadEnv });
620
+ }
621
+ await supabase.initialize({
622
+ supabaseUrl: requireEnv("SUPABASE_URL", env),
623
+ supabaseAnonKey: requireEnv("SUPABASE_ANON_KEY", env),
624
+ supabaseNeedAuthUrl: readEnv("SUPABASE_NEED_AUTH_URL", env),
625
+ supabaseNeedAuthAnonKey: readEnv("SUPABASE_NEED_AUTH_ANON_KEY", env),
626
+ });
627
+ }
628
+
629
+ /**
630
+ * Public base URL: `envKey` if set (trailing slash stripped), else `http://localhost:{port}`.
631
+ */
632
+ function publicBaseUrlFromEnv(port, options) {
633
+ const configured = readEnv(options.envKey, options.env ?? process.env);
634
+ if (configured != null) {
635
+ return configured.replace(/\/$/, "");
636
+ }
637
+ return `http://localhost:${port}`;
638
+ }
639
+
640
+ /** Per-file write queue — serializes read-modify-write for a single JSON path within one process. */
641
+ const writeChains = new Map();
642
+ function withSerializedFileWrites(filePath, operation) {
643
+ const previous = writeChains.get(filePath) ?? Promise.resolve();
644
+ const next = previous.then(operation, operation);
645
+ writeChains.set(filePath, next.then(() => undefined, () => undefined));
646
+ return next;
647
+ }
648
+
649
+ function mergeWithNested(defaults, current, patch, nestedKeys) {
650
+ const merged = {
651
+ ...defaults,
652
+ ...current,
653
+ ...patch,
654
+ };
655
+ for (const key of nestedKeys) {
656
+ const defaultNested = defaults[key];
657
+ if (defaultNested != null && typeof defaultNested === "object") {
658
+ merged[key] = {
659
+ ...defaultNested,
660
+ ...current?.[key],
661
+ ...patch[key],
662
+ };
663
+ }
664
+ }
665
+ return merged;
666
+ }
667
+ async function atomicWriteJson(filePath, data) {
668
+ await mkdir(dirname(filePath), { recursive: true });
669
+ const content = `${JSON.stringify(data, null, 2)}\n`;
670
+ JSON.parse(content);
671
+ const tempPath = `${filePath}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
672
+ try {
673
+ await writeFile(tempPath, content, "utf8");
674
+ await rename(tempPath, filePath);
675
+ }
676
+ catch (error) {
677
+ await unlink(tempPath).catch(() => undefined);
678
+ throw error;
679
+ }
680
+ }
681
+ /** JSON file-backed state with optional nested key merge and atomic writes. */
682
+ function createJsonFileStateStore(options) {
683
+ const { filePath, defaultState, nestedKeys = [], updatedAtKey } = options;
684
+ function touchUpdatedAt(state) {
685
+ if (updatedAtKey == null) {
686
+ return state;
687
+ }
688
+ return {
689
+ ...state,
690
+ [updatedAtKey]: new Date().toISOString(),
691
+ };
692
+ }
693
+ async function readFromDisk() {
694
+ try {
695
+ const raw = await readFile(filePath, "utf8");
696
+ const parsed = JSON.parse(raw);
697
+ return mergeWithNested(defaultState, parsed, {}, nestedKeys);
698
+ }
699
+ catch (error) {
700
+ if (error.code === "ENOENT") {
701
+ return mergeWithNested(defaultState, {}, {}, nestedKeys);
702
+ }
703
+ if (error instanceof SyntaxError) {
704
+ await unlink(filePath).catch(() => undefined);
705
+ return mergeWithNested(defaultState, {}, {}, nestedKeys);
706
+ }
707
+ throw error;
708
+ }
709
+ }
710
+ return {
711
+ read() {
712
+ return readFromDisk();
713
+ },
714
+ write(patch) {
715
+ return withSerializedFileWrites(filePath, async () => {
716
+ const current = await readFromDisk();
717
+ const next = touchUpdatedAt(mergeWithNested(defaultState, current, patch, nestedKeys));
718
+ await atomicWriteJson(filePath, next);
719
+ return next;
720
+ });
721
+ },
722
+ reset() {
723
+ return withSerializedFileWrites(filePath, async () => {
724
+ const next = touchUpdatedAt({ ...defaultState });
725
+ await atomicWriteJson(filePath, next);
726
+ return next;
727
+ });
728
+ },
729
+ };
730
+ }
731
+
732
+ /** Copy a Node.js Buffer view to a standalone ArrayBuffer. */
733
+ function nodeBufferToArrayBuffer(nodeBuffer) {
734
+ return nodeBuffer.buffer.slice(nodeBuffer.byteOffset, nodeBuffer.byteOffset + nodeBuffer.byteLength);
735
+ }
736
+ /** Read a local file with basic validation and SHA-256 digest. */
737
+ async function readAndVerifySourceFile(filePath, options = {}) {
738
+ const absolutePath = resolve(filePath);
739
+ const allowEmpty = options.allowEmpty === true;
740
+ try {
741
+ await access(absolutePath);
742
+ }
743
+ catch {
744
+ throw new Error(`Source file not found: ${absolutePath}`);
745
+ }
746
+ const fileStat = await stat(absolutePath);
747
+ if (!fileStat.isFile()) {
748
+ throw new Error(`Source path is not a file: ${absolutePath}`);
749
+ }
750
+ if (!allowEmpty && fileStat.size <= 0) {
751
+ throw new Error(`Source file is empty: ${absolutePath}`);
752
+ }
753
+ if (options.maxBytes != null && fileStat.size > options.maxBytes) {
754
+ throw new Error(`Source file exceeds maxBytes (${fileStat.size} > ${options.maxBytes}): ${absolutePath}`);
755
+ }
756
+ const nodeBuffer = await readFile(absolutePath);
757
+ const buffer = nodeBufferToArrayBuffer(nodeBuffer);
758
+ if (buffer.byteLength !== fileStat.size) {
759
+ throw new Error(`Source file size mismatch after read (${buffer.byteLength} !== ${fileStat.size}): ${absolutePath}`);
760
+ }
761
+ const digest = await sha256Hex(buffer);
762
+ if (options.expectedSha256 != null && digest.toLowerCase() !== options.expectedSha256.toLowerCase()) {
763
+ throw new Error(`Source file SHA-256 mismatch (expected ${options.expectedSha256}, got ${digest}): ${absolutePath}`);
764
+ }
765
+ return {
766
+ absolutePath,
767
+ buffer,
768
+ size: buffer.byteLength,
769
+ sha256: digest,
770
+ };
771
+ }
772
+
768
773
  /**
769
774
  * Build argv for `node --import … --import tsx <entry>`.
770
775
  * Use **relative** preload paths with `cwd: projectRoot` — Node 24 on Windows rejects
@@ -1607,11 +1612,14 @@ async function runServiceGuardTick(input) {
1607
1612
  }
1608
1613
  decision = "slot_ok";
1609
1614
  }
1610
- const { data: nodes = [] } = await scanTargetList({
1611
- category: CategoryNode.NODE,
1612
- maxRows: maxNodes,
1613
- });
1614
- const liveness = evaluateBusyNodeLiveness(nodes, {
1615
+ const nodes = serviceId == null
1616
+ ? []
1617
+ : ((await scanTargetList({
1618
+ category: CategoryNode.NODE,
1619
+ filterList: [{ field: "name", operator: "eq", value: serviceId }],
1620
+ maxRows: maxNodes,
1621
+ })).data ?? []);
1622
+ const liveness = evaluateBusyNodeLiveness(nodesForTaskLiveness(nodes), {
1615
1623
  staleMs: taskNodeStaleMs,
1616
1624
  now: nowMs,
1617
1625
  excludeNodeId: nodeId,
@@ -1728,6 +1736,7 @@ function registerServiceGuardRunner(options) {
1728
1736
  }
1729
1737
 
1730
1738
  const UPLOAD_LANE = "slow";
1739
+ const MAX_UPLOADS_PER_COLLECT_TICK = 20;
1731
1740
  /** Per serviceId — guard collect-log tick runs GC at most once per `gc.intervalMs`. */
1732
1741
  const lastGcAtMsByServiceId = new Map();
1733
1742
  async function pathExists$1(filePath) {
@@ -1759,6 +1768,9 @@ async function readBatchTmpFile(tmpPath) {
1759
1768
  function processMetaKey(serviceId, processRole) {
1760
1769
  return `${serviceId}:${processRole}`;
1761
1770
  }
1771
+ function syncedMarkerPath(jsonPath) {
1772
+ return jsonPath.replace(/\.json$/, ".synced");
1773
+ }
1762
1774
  async function uploadTmpBatch(input) {
1763
1775
  const parsed = parseLogSpoolBatchFilename(input.fileName);
1764
1776
  if (parsed == null) {
@@ -1767,6 +1779,7 @@ async function uploadTmpBatch(input) {
1767
1779
  }
1768
1780
  const jsonFileName = input.fileName.replace(/\.tmp$/, ".json");
1769
1781
  const jsonPath = join(logSpoolProcessDir(input.spoolRoot, input.serviceId, input.processRole), jsonFileName);
1782
+ const syncedPath = syncedMarkerPath(jsonPath);
1770
1783
  if (await pathExists$1(jsonPath)) {
1771
1784
  try {
1772
1785
  await unlink(input.tmpPath);
@@ -1780,6 +1793,20 @@ async function uploadTmpBatch(input) {
1780
1793
  }
1781
1794
  return "skipped";
1782
1795
  }
1796
+ if (await pathExists$1(syncedPath)) {
1797
+ try {
1798
+ await rename(input.tmpPath, jsonPath);
1799
+ }
1800
+ catch {
1801
+ try {
1802
+ await unlink(input.tmpPath);
1803
+ }
1804
+ catch {
1805
+ // best-effort
1806
+ }
1807
+ }
1808
+ return "skipped";
1809
+ }
1783
1810
  const batch = await readBatchTmpFile(input.tmpPath);
1784
1811
  if (batch == null) {
1785
1812
  spoolLogger.warn("collect-log skipped — tmp failed validation", {
@@ -1796,18 +1823,10 @@ async function uploadTmpBatch(input) {
1796
1823
  return "failed";
1797
1824
  }
1798
1825
  const processKey = processMetaKey(input.serviceId, input.processRole);
1799
- // TODO: `lane` is legacy transport metadata — scheduled for removal; fixed to "slow" for downstream decode compatibility.
1800
- const idempotencyKey = computeLogBatchIdempotencyKey({
1801
- service: input.serviceValue,
1802
- process: processKey,
1803
- lane: UPLOAD_LANE,
1804
- entries: batch.entries,
1805
- });
1806
1826
  const draft = buildLogListDraft({
1807
1827
  service: input.serviceValue,
1808
1828
  process: processKey,
1809
1829
  lane: UPLOAD_LANE,
1810
- idempotencyKey,
1811
1830
  entries: batch.entries,
1812
1831
  });
1813
1832
  try {
@@ -1822,8 +1841,21 @@ async function uploadTmpBatch(input) {
1822
1841
  });
1823
1842
  return "failed";
1824
1843
  }
1844
+ try {
1845
+ await writeFile(syncedPath, `${Date.now()}\n`, "utf8");
1846
+ }
1847
+ catch (error) {
1848
+ const message = error instanceof Error ? error.message : String(error);
1849
+ spoolLogger.warn("collect-log synced marker write failed", { syncedPath, error: message });
1850
+ }
1825
1851
  try {
1826
1852
  await rename(input.tmpPath, jsonPath);
1853
+ try {
1854
+ await unlink(syncedPath);
1855
+ }
1856
+ catch {
1857
+ // best-effort
1858
+ }
1827
1859
  }
1828
1860
  catch (error) {
1829
1861
  const message = error instanceof Error ? error.message : String(error);
@@ -1832,13 +1864,12 @@ async function uploadTmpBatch(input) {
1832
1864
  jsonPath,
1833
1865
  error: message,
1834
1866
  });
1835
- return "failed";
1867
+ return "uploaded";
1836
1868
  }
1837
1869
  spoolLogger.info("collect-log uploaded batch", {
1838
1870
  processRole: input.processRole,
1839
1871
  fileName: jsonFileName,
1840
1872
  entryCount: batch.entries.length,
1841
- idempotencyKey,
1842
1873
  });
1843
1874
  return "uploaded";
1844
1875
  }
@@ -1888,21 +1919,21 @@ async function gcSyncedJsonFiles(input) {
1888
1919
  continue;
1889
1920
  }
1890
1921
  for (const name of names) {
1891
- if (!name.endsWith(".json")) {
1922
+ if (!name.endsWith(".json") && !name.endsWith(".synced")) {
1892
1923
  continue;
1893
1924
  }
1894
- if (parseLogSpoolBatchFilename(name) == null) {
1925
+ if (parseLogSpoolBatchFilename(name) == null && !name.endsWith(".synced")) {
1895
1926
  continue;
1896
1927
  }
1897
- const jsonPath = join(processDir, name);
1928
+ const filePath = join(processDir, name);
1898
1929
  try {
1899
- const fileStat = await stat(jsonPath);
1930
+ const fileStat = await stat(filePath);
1900
1931
  if (input.nowMs - fileStat.mtimeMs <= input.syncedRetentionMs) {
1901
1932
  continue;
1902
1933
  }
1903
- await unlink(jsonPath);
1934
+ await unlink(filePath);
1904
1935
  removed += 1;
1905
- spoolLogger.info("collect-log gc removed synced json", {
1936
+ spoolLogger.info("collect-log gc removed synced file", {
1906
1937
  fileName: name,
1907
1938
  processRole,
1908
1939
  });
@@ -1924,7 +1955,7 @@ function shouldRunGc(serviceId, nowMs, intervalMs) {
1924
1955
  }
1925
1956
  /**
1926
1957
  * Guard-only: upload pending `.tmp` batches, rename to `.json`, then periodic GC.
1927
- * Upload completion is implied by `.json` presence; no sync-state file.
1958
+ * Post success is tracked via `.json` or `.synced` marker (prevents duplicate DB inserts).
1928
1959
  */
1929
1960
  async function runCollectLogTick(input) {
1930
1961
  const config = resolveLogSpoolConfig(input.config);
@@ -1937,6 +1968,7 @@ async function runCollectLogTick(input) {
1937
1968
  gcTmpRemoved: 0,
1938
1969
  gcSyncedRemoved: 0,
1939
1970
  };
1971
+ let uploadsThisTick = 0;
1940
1972
  for (const processRole of resolveAllLogSpoolProcessRoles()) {
1941
1973
  const processDir = logSpoolProcessDir(spoolRoot, input.serviceId, processRole);
1942
1974
  let names = [];
@@ -1950,6 +1982,9 @@ async function runCollectLogTick(input) {
1950
1982
  if (!name.endsWith(".tmp")) {
1951
1983
  continue;
1952
1984
  }
1985
+ if (uploadsThisTick >= MAX_UPLOADS_PER_COLLECT_TICK) {
1986
+ break;
1987
+ }
1953
1988
  const status = await uploadTmpBatch({
1954
1989
  serviceId: input.serviceId,
1955
1990
  serviceValue: input.serviceValue,
@@ -1961,6 +1996,7 @@ async function runCollectLogTick(input) {
1961
1996
  });
1962
1997
  if (status === "uploaded") {
1963
1998
  result.uploaded += 1;
1999
+ uploadsThisTick += 1;
1964
2000
  }
1965
2001
  else if (status === "skipped") {
1966
2002
  result.skipped += 1;
@@ -2056,6 +2092,9 @@ class TriggerNode extends BaseNodeRuntime {
2056
2092
  }
2057
2093
  this.loopIntervalMs = loopIntervalMs;
2058
2094
  }
2095
+ getNodeKind() {
2096
+ return NodeKind.TRIGGER;
2097
+ }
2059
2098
  getLoopIntervalMs() {
2060
2099
  return this.loopIntervalMs;
2061
2100
  }
@@ -2131,6 +2170,9 @@ class ServiceGuardNode extends TriggerNode {
2131
2170
  this.options = options;
2132
2171
  this.businessReadyTimeoutMs = options.businessReadyTimeoutMs ?? DEFAULT_BUSINESS_READY_TIMEOUT_MS;
2133
2172
  }
2173
+ getNodeKind() {
2174
+ return NodeKind.GUARD;
2175
+ }
2134
2176
  /** Register the guard runner and return a ready-to-start node. */
2135
2177
  static create(options) {
2136
2178
  registerServiceGuardRunner({
@@ -2541,9 +2583,9 @@ function createServiceHost(options) {
2541
2583
  if (options.onRegistryClaimed != null) {
2542
2584
  await options.onRegistryClaimed(hostCtx);
2543
2585
  }
2586
+ process.env[LOG_SPOOL_SERVICE_ID_ENV] = session.service.id;
2544
2587
  const enableSpool = options.enableLogSpoolAfterClaim ?? true;
2545
2588
  if (enableSpool && logSpoolEnabledFromEnv()) {
2546
- process.env[LOG_SPOOL_SERVICE_ID_ENV] = session.service.id;
2547
2589
  await ensureLogSpoolFromEnv({
2548
2590
  serviceId: session.service.id,
2549
2591
  serviceValue: options.serviceValue,
@@ -2601,6 +2643,7 @@ async function runSingleProcessService(options) {
2601
2643
  logger,
2602
2644
  logTopic,
2603
2645
  });
2646
+ process.env[LOG_SPOOL_SERVICE_ID_ENV] = session.service.id;
2604
2647
  try {
2605
2648
  await options.run({ service: session.service, session });
2606
2649
  }
@@ -4580,6 +4623,9 @@ class TaskNode extends BaseNodeRuntime {
4580
4623
  constructor() {
4581
4624
  super("taskNode");
4582
4625
  }
4626
+ getNodeKind() {
4627
+ return NodeKind.TASK;
4628
+ }
4583
4629
  async onBeforeRegisterNode(logger) {
4584
4630
  const { availableTaskList, includeRemote } = await TaskManager.registerTasks({ logger });
4585
4631
  this._availableTaskList = availableTaskList;
@@ -5034,5 +5080,5 @@ function buildFireKey(trigger, now = new Date()) {
5034
5080
  return buildDailyFireKey(schedule, now);
5035
5081
  }
5036
5082
 
5037
- export { BaseNodeRuntime, COLLECT_LOG_RUNNER_KEY, CategoryCommand, CategoryLink, CategoryNode, CategoryRepo, CategoryTrigger, CommandType, EMPTY_REGISTRY_SLOT_RUNTIME_STATE, IDEA_IMAGE_TEMP_DIR, IDEA_TEMP_DOWNLOAD_PATH_SUFFIX, LOG_SPOOL_SERVICE_ID_ENV, LOG_TOPIC_TRIGGER, LogLevel, MAX_POLL_TARGET_LIST_SIZE, MEDIA_CONTENT_HASH_ALGORITHM, ManagedChildProcesses, NodeStatus, PROVIDER_TELEGRAM, RepoManager, ResultCode, SERVICE_GUARD_RUNNER_KEY, ServiceGuardNode, ServiceRegistryError, TASK_LOCAL_PACKAGE_CONFIG_FILENAME, TASK_REPO_SCRIPT_CATEGORY, TASK_REPO_USAGE, TASK_RUNNER_CONFIG_DIR, TASK_RUNNER_ROOT_CONFIG_FILENAME, TASK_RUNNER_ROOT_CONFIG_LEGACY_RELATIVE_PATH, TASK_RUNNER_ROOT_CONFIG_RELATIVE_PATH, TRIGGER_LOOP_INTERVAL_MS, TRIGGER_RUNNER_DEFAULT_RETRY_COUNT, TRIGGER_RUNNER_DEFAULT_RETRY_DELAY_MS, TaskManager, TaskNode, TaskRepoValidation, TaskStatus, TaskStatusAction, TriggerManager, TriggerNode, TriggerStatus, applyRegistrySlotGuardStep, buildDailyFireKey, buildFeedLinkDraft, buildFireKey, buildIdeaPasteRelativePath, buildIdeaTempDownloadLocator, buildMediaLinkDraft, buildNodeImportArgs, callTelegramApi, checkFeedLocalAvailability, checkFeedOssAvailability, checkMediaAvailability, claimServiceRegistrySlot, createFeed, createJsonFileStateStore, createL3ChildLauncher, createLogSpoolCoordinator, createLogger, createManagedChildProcesses, createPathsExistCheck, createRequiredEnvCheck, createServiceHost, createServiceRuntimeStateStore, createSupabaseReachableCheck, createTarget, createTelegramStorageProvider, downloadTelegramChunk, enableLogSpoolFromEnvInChild, encodeTelegramChunkUrl, ensureLogSpoolFromEnv, evaluateBusyNodeLiveness, feedLinkDedupFilters, fetchBinaryWithRetry, fetchWithRetry, findMediaLink, generateResponse, getConfigFileDir, getLogSpoolStats, getMainLogSpoolWriterStats, getPollCommandList, getPollCommandListSchema, getPossibleTarget, getScanRemoteRepoValues, getTarget, guardRetryAfterSec, guessMediaMime, hashIdeaPasteImage, importJsConfigModule, initSupabaseFromStandardEnv, isChildProcessRunning, isCreateTargetAlreadyExistsError, isDailyScheduleDue, isFeedIngestSource, isFeedValue, isGuardAvailable, isHttpUrl, isLogEntry, isLogSpoolEnabled, isMediaValue, isOpaqueChunkUrl, isOptimisticLockResponse, isRetryableHttpStatus, isTriggerDue, loadCachedJsConfigModule, loadEnvFiles, logManager, logSpoolEnabledFromEnv, markWorkerSpawned, mediaLinkDedupFilters, nodeBufferToArrayBuffer, parseIdeaTempDownloadLocator, parseTelegramChunkUrl, patchChangeNodeStatus, patchChangeTaskStatus, patchClaimTask, patchNodeHeartBeat, patchServiceRuntime, patchStopNode, patchTriggerFired, patchTriggerFiredSchema, pathExists, pollTargetList, pollUntil, postCommand, postCommandSchema, postRegisterNode, postTarget, postTaskSchema, postTaskWithValidation, postTrigger, postTriggerSchema, probeMediaOriginal, publicBaseUrlFromEnv, readAndVerifySourceFile, readEnv, registerCollectLogRunner, registerFeed, registerMediaLink, registerServiceGuardRunner, registrySlotRuntimePatchFromGuardResult, requireEnv, resolveFirstExistingPath, resolveLogSpoolRoot, resolvePathFromBaseDir, resolvePathFromConfigFile, resolvePathFromCwd, resolveTelegramStorageOptions, runCollectLogTick, runReadinessChecks, runReadinessGate, runRegistrySlotGuardCheck, runServiceGuardTick, runSingleProcessService, scanEnabledTriggers, scanEnabledTriggersSchema, scanTargetList, sha256Hex, shutdownLogSpool, shutdownLogSpoolFromEnv, spawnTsxChild, supabase, telegramDownloadBinary, telegramFileDownloadUrl, toFileImportHref, updateTarget, updateTargetDetails, validateTaskRepoAndParams, validateWithSchema, waitForServiceReady };
5083
+ export { BaseNodeRuntime, COLLECT_LOG_RUNNER_KEY, CategoryCommand, CategoryLink, CategoryNode, CategoryRepo, CategoryTrigger, CommandType, EMPTY_REGISTRY_SLOT_RUNTIME_STATE, IDEA_IMAGE_TEMP_DIR, IDEA_TEMP_DOWNLOAD_PATH_SUFFIX, LOG_SPOOL_SERVICE_ID_ENV, LOG_TOPIC_TRIGGER, LogLevel, MAX_POLL_TARGET_LIST_SIZE, MEDIA_CONTENT_HASH_ALGORITHM, ManagedChildProcesses, NodeKind, NodeStatus, PROVIDER_TELEGRAM, RepoManager, ResultCode, SERVICE_GUARD_RUNNER_KEY, ServiceGuardNode, ServiceRegistryError, TASK_LOCAL_PACKAGE_CONFIG_FILENAME, TASK_REPO_SCRIPT_CATEGORY, TASK_REPO_USAGE, TASK_RUNNER_CONFIG_DIR, TASK_RUNNER_ROOT_CONFIG_FILENAME, TASK_RUNNER_ROOT_CONFIG_LEGACY_RELATIVE_PATH, TASK_RUNNER_ROOT_CONFIG_RELATIVE_PATH, TRIGGER_LOOP_INTERVAL_MS, TRIGGER_RUNNER_DEFAULT_RETRY_COUNT, TRIGGER_RUNNER_DEFAULT_RETRY_DELAY_MS, TaskManager, TaskNode, TaskRepoValidation, TaskStatus, TaskStatusAction, TriggerManager, TriggerNode, TriggerStatus, applyRegistrySlotGuardStep, buildDailyFireKey, buildFeedLinkDraft, buildFireKey, buildIdeaPasteRelativePath, buildIdeaTempDownloadLocator, buildMediaLinkDraft, buildNodeImportArgs, callTelegramApi, checkFeedLocalAvailability, checkFeedOssAvailability, checkMediaAvailability, claimServiceRegistrySlot, createFeed, createJsonFileStateStore, createL3ChildLauncher, createLogSpoolCoordinator, createLogger, createManagedChildProcesses, createPathsExistCheck, createRequiredEnvCheck, createServiceHost, createServiceRuntimeStateStore, createSupabaseReachableCheck, createTarget, createTelegramStorageProvider, downloadTelegramChunk, enableLogSpoolFromEnvInChild, encodeTelegramChunkUrl, ensureLogSpoolFromEnv, evaluateBusyNodeLiveness, feedLinkDedupFilters, fetchBinaryWithRetry, fetchWithRetry, findMediaLink, generateResponse, getConfigFileDir, getLogSpoolStats, getMainLogSpoolWriterStats, getPollCommandList, getPollCommandListSchema, getPossibleTarget, getScanRemoteRepoValues, getTarget, guardRetryAfterSec, guessMediaMime, hashIdeaPasteImage, importJsConfigModule, initSupabaseFromStandardEnv, isChildProcessRunning, isCreateTargetAlreadyExistsError, isDailyScheduleDue, isFeedIngestSource, isFeedValue, isGuardAvailable, isHttpUrl, isLogEntry, isLogSpoolEnabled, isMediaValue, isOpaqueChunkUrl, isOptimisticLockResponse, isRetryableHttpStatus, isTriggerDue, loadCachedJsConfigModule, loadEnvFiles, logManager, logSpoolEnabledFromEnv, markWorkerSpawned, mediaLinkDedupFilters, nodeBufferToArrayBuffer, nodesForTaskLiveness, parseIdeaTempDownloadLocator, parseTelegramChunkUrl, patchChangeNodeStatus, patchChangeTaskStatus, patchClaimTask, patchNodeHeartBeat, patchServiceRuntime, patchStopNode, patchTriggerFired, patchTriggerFiredSchema, pathExists, pollTargetList, pollUntil, postCommand, postCommandSchema, postRegisterNode, postTarget, postTaskSchema, postTaskWithValidation, postTrigger, postTriggerSchema, probeMediaOriginal, publicBaseUrlFromEnv, readAndVerifySourceFile, readEnv, registerCollectLogRunner, registerFeed, registerMediaLink, registerServiceGuardRunner, registrySlotRuntimePatchFromGuardResult, requireEnv, requireNodeServiceIdFromEnv, resolveFirstExistingPath, resolveLogSpoolRoot, resolvePathFromBaseDir, resolvePathFromConfigFile, resolvePathFromCwd, resolveTelegramStorageOptions, runCollectLogTick, runReadinessChecks, runReadinessGate, runRegistrySlotGuardCheck, runServiceGuardTick, runSingleProcessService, scanEnabledTriggers, scanEnabledTriggersSchema, scanTargetList, sha256Hex, shutdownLogSpool, shutdownLogSpoolFromEnv, spawnTsxChild, supabase, telegramDownloadBinary, telegramFileDownloadUrl, toFileImportHref, updateTarget, updateTargetDetails, validateTaskRepoAndParams, validateWithSchema, waitForServiceReady };
5038
5084
  //# sourceMappingURL=node.js.map