@lunora/config 1.0.0-alpha.69 → 1.0.0-alpha.70

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.
package/dist/index.d.mts CHANGED
@@ -772,6 +772,29 @@ interface ReconcileCompatibilityDateResult {
772
772
  * is enabled but the date is below the minimum required.
773
773
  */
774
774
  declare const reconcileWranglerCompatibilityDate: (projectRoot: string) => ReconcileCompatibilityDateResult;
775
+ interface ReconcileResult {
776
+ /** `true` when `wrangler.jsonc` was rewritten. */
777
+ changed: boolean;
778
+ /** Human-readable reason when reconciliation was skipped (for logging). */
779
+ reason?: string;
780
+ /** Resolved wrangler path, or `undefined` when none was found. */
781
+ wranglerPath?: string;
782
+ }
783
+ /**
784
+ * Reconcile the codegen-derived cron schedules into the project's
785
+ * `wrangler.jsonc` `triggers.crons` array, preserving comments and formatting
786
+ * via `jsonc-parser`'s structural edits.
787
+ *
788
+ * When `triggers.crons` already matches `cronTriggers`, nothing is written (so
789
+ * we don't churn the file or trip the dev server's file watcher). When the
790
+ * project declares no crons, a stale non-empty array is cleared so removed
791
+ * crons stop firing.
792
+ *
793
+ * This intentionally writes the SAME `triggers.crons` shape the
794
+ * `@lunora/config` validator accepts, so the wrangler validator never fights
795
+ * the generated value.
796
+ */
797
+ declare const reconcileWranglerCrons: (projectRoot: string, cronTriggers: ReadonlyArray<string>) => ReconcileResult;
775
798
  /**
776
799
  * The wrangler config sections Lunora can safely flip to remote mode in dev,
777
800
  * each with the human label used in logs and the structural `shape` the entry
@@ -1294,6 +1317,37 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1294
1317
  declare const paintBadge: (spec: BadgeSpec) => string;
1295
1318
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1296
1319
  declare const paintAnswer: (text: string) => string;
1320
+ /**
1321
+ * Single source of truth for "does this wrangler config enable Workers
1322
+ * Cache?" and "what compatibility_date does that require?".
1323
+ *
1324
+ * Before this module, `reconcile-compatibility-date.ts` (auto-bump) and
1325
+ * `wrangler-validator.ts` (validation) each carried their own
1326
+ * `WORKERS_CACHE_MIN_DATE` literal and their own top-level/`exports[]`
1327
+ * cache-enabled walk — two copies of the same fact that could silently drift
1328
+ * apart (a date bumped in one file without the other would either validate a
1329
+ * config the reconciler wouldn't produce, or vice versa).
1330
+ */
1331
+ /** The `compatibility_date` Workers Cache (`cache.enabled: true`) requires. */
1332
+ declare const WORKERS_CACHE_MIN_DATE = "2026-05-01";
1333
+ /** The subset of a parsed `wrangler.jsonc` the cache-enabled check reads. */
1334
+ interface WranglerCacheShape {
1335
+ cache?: {
1336
+ enabled?: boolean;
1337
+ } | null;
1338
+ exports?: Record<string, {
1339
+ cache?: {
1340
+ enabled?: boolean;
1341
+ } | null;
1342
+ } | null> | null;
1343
+ }
1344
+ /**
1345
+ * Whether Workers Cache is enabled anywhere in a parsed wrangler config — the
1346
+ * top-level `cache.enabled` toggle, or a per-export override in
1347
+ * `exports[name].cache.enabled` (Workers can scope cache per named export).
1348
+ * `undefined`/`null` (an unparsed or absent config) is treated as disabled.
1349
+ */
1350
+ declare const isCacheEnabled: (parsed: WranglerCacheShape | null | undefined) => boolean;
1297
1351
  /** Candidate wrangler config filenames, in the order every consumer probes them. */
1298
1352
  declare const WRANGLER_FILES: readonly ["wrangler.jsonc", "wrangler.json"];
1299
1353
  /** Locate the project's wrangler config, or `undefined` when none exists. */
@@ -1530,4 +1584,4 @@ interface WranglerProjectValidationResult {
1530
1584
  * `{ problems, wranglerPath }` shape plus the structured `report`.
1531
1585
  */
1532
1586
  declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
1533
- export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredAgent, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WRANGLER_FILES, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
1587
+ export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredAgent, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isCacheEnabled, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
package/dist/index.d.ts CHANGED
@@ -772,6 +772,29 @@ interface ReconcileCompatibilityDateResult {
772
772
  * is enabled but the date is below the minimum required.
773
773
  */
774
774
  declare const reconcileWranglerCompatibilityDate: (projectRoot: string) => ReconcileCompatibilityDateResult;
775
+ interface ReconcileResult {
776
+ /** `true` when `wrangler.jsonc` was rewritten. */
777
+ changed: boolean;
778
+ /** Human-readable reason when reconciliation was skipped (for logging). */
779
+ reason?: string;
780
+ /** Resolved wrangler path, or `undefined` when none was found. */
781
+ wranglerPath?: string;
782
+ }
783
+ /**
784
+ * Reconcile the codegen-derived cron schedules into the project's
785
+ * `wrangler.jsonc` `triggers.crons` array, preserving comments and formatting
786
+ * via `jsonc-parser`'s structural edits.
787
+ *
788
+ * When `triggers.crons` already matches `cronTriggers`, nothing is written (so
789
+ * we don't churn the file or trip the dev server's file watcher). When the
790
+ * project declares no crons, a stale non-empty array is cleared so removed
791
+ * crons stop firing.
792
+ *
793
+ * This intentionally writes the SAME `triggers.crons` shape the
794
+ * `@lunora/config` validator accepts, so the wrangler validator never fights
795
+ * the generated value.
796
+ */
797
+ declare const reconcileWranglerCrons: (projectRoot: string, cronTriggers: ReadonlyArray<string>) => ReconcileResult;
775
798
  /**
776
799
  * The wrangler config sections Lunora can safely flip to remote mode in dev,
777
800
  * each with the human label used in logs and the structural `shape` the entry
@@ -1294,6 +1317,37 @@ declare const badgeWidth: (_spec: BadgeSpec) => number;
1294
1317
  declare const paintBadge: (spec: BadgeSpec) => string;
1295
1318
  /** Dim continuation text (a step's chosen answer, shown under the question). */
1296
1319
  declare const paintAnswer: (text: string) => string;
1320
+ /**
1321
+ * Single source of truth for "does this wrangler config enable Workers
1322
+ * Cache?" and "what compatibility_date does that require?".
1323
+ *
1324
+ * Before this module, `reconcile-compatibility-date.ts` (auto-bump) and
1325
+ * `wrangler-validator.ts` (validation) each carried their own
1326
+ * `WORKERS_CACHE_MIN_DATE` literal and their own top-level/`exports[]`
1327
+ * cache-enabled walk — two copies of the same fact that could silently drift
1328
+ * apart (a date bumped in one file without the other would either validate a
1329
+ * config the reconciler wouldn't produce, or vice versa).
1330
+ */
1331
+ /** The `compatibility_date` Workers Cache (`cache.enabled: true`) requires. */
1332
+ declare const WORKERS_CACHE_MIN_DATE = "2026-05-01";
1333
+ /** The subset of a parsed `wrangler.jsonc` the cache-enabled check reads. */
1334
+ interface WranglerCacheShape {
1335
+ cache?: {
1336
+ enabled?: boolean;
1337
+ } | null;
1338
+ exports?: Record<string, {
1339
+ cache?: {
1340
+ enabled?: boolean;
1341
+ } | null;
1342
+ } | null> | null;
1343
+ }
1344
+ /**
1345
+ * Whether Workers Cache is enabled anywhere in a parsed wrangler config — the
1346
+ * top-level `cache.enabled` toggle, or a per-export override in
1347
+ * `exports[name].cache.enabled` (Workers can scope cache per named export).
1348
+ * `undefined`/`null` (an unparsed or absent config) is treated as disabled.
1349
+ */
1350
+ declare const isCacheEnabled: (parsed: WranglerCacheShape | null | undefined) => boolean;
1297
1351
  /** Candidate wrangler config filenames, in the order every consumer probes them. */
1298
1352
  declare const WRANGLER_FILES: readonly ["wrangler.jsonc", "wrangler.json"];
1299
1353
  /** Locate the project's wrangler config, or `undefined` when none exists. */
@@ -1530,4 +1584,4 @@ interface WranglerProjectValidationResult {
1530
1584
  * `{ problems, wranglerPath }` shape plus the structured `report`.
1531
1585
  */
1532
1586
  declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
1533
- export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredAgent, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WRANGLER_FILES, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
1587
+ export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverAgentInfoResult, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredAgent, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type ReconcileCompatibilityDateResult, type ReconcileResult as ReconcileCronsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WORKERS_CACHE_MIN_DATE, WRANGLER_FILES, type WranglerCacheShape, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverAgentInfo, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isCacheEnabled, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptText, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, reconcileWranglerCompatibilityDate, reconcileWranglerCrons, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ export { streamContainerLogs } from './packem_shared/streamContainerLogs-BZ4cOZw
6
6
  export { detectFramework, readProjectDependencyNames } from './packem_shared/detectFramework-U08038Yp.mjs';
7
7
  export { DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, claimDevServerState, clearDevServerState, isProcessAlive, isRecordedProcessCurrent, readDevServerState, readLiveDevServerState, updateDevServerState, writeDevServerState } from './packem_shared/DEV_DAEMON_ENV-FIEtW7Fz.mjs';
8
8
  export { DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, parseDevVariableEntries } from './packem_shared/DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs';
9
- export { inferLunoraBindings, packageNamesFromBindings } from './packem_shared/inferLunoraBindings-CPmUh1LN.mjs';
9
+ export { inferLunoraBindings, packageNamesFromBindings } from './packem_shared/inferLunoraBindings-BcvvtpSG.mjs';
10
10
  export { LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, readLinkedProject, writeLinkedProject } from './packem_shared/LINKED_PROJECT_DIR-CXwXzV_C.mjs';
11
11
  export { LUNORA_EVENT_SOURCE, formatLunoraEvent } from './packem_shared/LUNORA_EVENT_SOURCE-D2fDeGB6.mjs';
12
12
  export { default as LunoraReporter } from './packem_shared/LunoraReporter-Ci-bDCK9.mjs';
@@ -14,7 +14,8 @@ export { PACKAGE_SECRETS_REGISTRY, secretsForPackages } from './packem_shared/PA
14
14
  export { LUNORA_CONFIG_FILE, interpretRemote, readProjectRemotePreference } from './packem_shared/LUNORA_CONFIG_FILE-CtcIcB5-.mjs';
15
15
  export { createConfirm, isInteractive, promptMultiSelect, promptSelect, promptText, promptYesNo } from './packem_shared/createConfirm-BMikeJC9.mjs';
16
16
  export { reconcileWranglerBindings } from './packem_shared/reconcileWranglerBindings-2Cww5VLa.mjs';
17
- export { reconcileWranglerCompatibilityDate } from './packem_shared/reconcileWranglerCompatibilityDate-D5Bqjk4P.mjs';
17
+ export { reconcileWranglerCompatibilityDate } from './packem_shared/reconcileWranglerCompatibilityDate-C8c497ag.mjs';
18
+ export { reconcileWranglerCrons } from './packem_shared/reconcileWranglerCrons-DvsceVFz.mjs';
18
19
  export { REMOTE_ELIGIBLE_KEYS, injectRemoteFlags, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, resolveRemoteEnabled } from './packem_shared/REMOTE_ELIGIBLE_KEYS-C-F_Flgy.mjs';
19
20
  export { buildPackageSecretsBlock, ensureDevVariables, ensureDevVarsExample, fillDevSecrets, generateSecretValue, isMintableSecretKey, isPlaceholderValue, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, requiredSecrets } from './packem_shared/buildPackageSecretsBlock-B-dWb-Sa.mjs';
20
21
  export { applyAdditiveEdit, classifyEdit } from './packem_shared/applyAdditiveEdit-C-snTFEV.mjs';
@@ -22,7 +23,8 @@ export { parseSchema } from './packem_shared/parseSchema-DSeyktvG.mjs';
22
23
  export { classifyPolicyEdit, scaffoldPolicyFile, wireRlsIntoProcedure } from './packem_shared/classifyPolicyEdit-BHeAqF8P.mjs';
23
24
  export { discoverSchemaInfo } from './packem_shared/discoverSchemaInfo-BB-CKlTK.mjs';
24
25
  export { ACCENT, BADGES, BADGE_COLUMN_WIDTH, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, STEP_BADGE_NAMES, badgeLead, badgeWidth, padBadge, paintAnswer, paintBadge } from './packem_shared/ACCENT-DW1XJn8i.mjs';
26
+ export { WORKERS_CACHE_MIN_DATE, isCacheEnabled } from './packem_shared/WORKERS_CACHE_MIN_DATE-CaXbS7CX.mjs';
25
27
  export { discoverWorkflowInfo } from './packem_shared/discoverWorkflowInfo-CedvR0mn.mjs';
26
28
  export { WRANGLER_FILES, findWranglerFile, readWranglerJsonc } from './packem_shared/WRANGLER_FILES-DwSuC-Kn.mjs';
27
29
  export { collectWranglerSecretVariables, scanWranglerVariablesForSecrets } from './packem_shared/collectWranglerSecretVariables-p4ezBYQ4.mjs';
28
- export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer } from './packem_shared/REQUIRED_COMPATIBILITY_DATE-CoKkA1uk.mjs';
30
+ export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer } from './packem_shared/REQUIRED_COMPATIBILITY_DATE-DP0SFVy9.mjs';
@@ -1,6 +1,7 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { discoverSchemaInfo } from './discoverSchemaInfo-BB-CKlTK.mjs';
4
+ import { isCacheEnabled, WORKERS_CACHE_MIN_DATE } from './WORKERS_CACHE_MIN_DATE-CaXbS7CX.mjs';
4
5
  import { findWranglerFile, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
5
6
 
6
7
  const REQUIRED_COMPATIBILITY_DATE = "2026-04-07";
@@ -508,10 +509,7 @@ const validateWranglerConfig = (wrangler, schema) => {
508
509
  } else if (compatibilityDate < REQUIRED_COMPATIBILITY_DATE) {
509
510
  errors.push(`compatibility_date must be >= "${REQUIRED_COMPATIBILITY_DATE}" (got "${compatibilityDate || "<missing>"}")`);
510
511
  }
511
- const WORKERS_CACHE_MIN_DATE = "2026-05-01";
512
- const cacheEnabled = typeof wrangler.cache === "object" && wrangler.cache !== null && wrangler.cache.enabled === true;
513
- const exportsWithCache = typeof wrangler.exports === "object" && wrangler.exports !== null && Object.values(wrangler.exports).some((entry) => typeof entry === "object" && entry !== null && entry.cache?.enabled === true);
514
- if ((cacheEnabled || exportsWithCache) && ISO_DATE_PATTERN.test(compatibilityDate) && compatibilityDate < WORKERS_CACHE_MIN_DATE) {
512
+ if (isCacheEnabled(wrangler) && ISO_DATE_PATTERN.test(compatibilityDate) && compatibilityDate < WORKERS_CACHE_MIN_DATE) {
515
513
  errors.push(`cache.enabled requires compatibility_date >= "${WORKERS_CACHE_MIN_DATE}" (got "${compatibilityDate || "<missing>"}")`);
516
514
  }
517
515
  if (schema?.hasGlobalTable) {
@@ -0,0 +1,11 @@
1
+ const WORKERS_CACHE_MIN_DATE = "2026-05-01";
2
+ const isCacheEnabled = (parsed) => {
3
+ if (!parsed) {
4
+ return false;
5
+ }
6
+ const topLevel = typeof parsed.cache === "object" && parsed.cache !== null && parsed.cache.enabled === true;
7
+ const inExports = typeof parsed.exports === "object" && parsed.exports !== null && Object.values(parsed.exports).some((entry) => typeof entry === "object" && entry !== null && entry.cache?.enabled === true);
8
+ return topLevel || inExports;
9
+ };
10
+
11
+ export { WORKERS_CACHE_MIN_DATE, isCacheEnabled };
@@ -54,7 +54,35 @@ const ENV_DB_PATTERN = /\benv\s*\.\s*DB\b/;
54
54
  const ENV_AI_PATTERN = /\benv\s*\.\s*AI\b/;
55
55
  const CTX_PIPELINES_PATTERN = /\bctx\s*\.\s*pipelines\b/;
56
56
  const TYPE_ONLY_IMPORT_PATTERN = /^\s*import\s+type\b/;
57
- const SANDBOX_BROWSER_TOOL_PATTERN = /import\s+\{[^}]*\bbrowserTool\b[^}]*\}\s+from\s+["']@lunora\/agent(?:\/sandbox)?["']/;
57
+ const SANDBOX_MODULE_SPECIFIERS = /* @__PURE__ */ new Set(["@lunora/agent", "@lunora/agent/sandbox"]);
58
+ const extractImportSpecifierList = (statementText) => {
59
+ const openBraceIndex = statementText.indexOf("{");
60
+ if (openBraceIndex === -1) {
61
+ return "";
62
+ }
63
+ const closeBraceIndex = statementText.indexOf("}", openBraceIndex + 1);
64
+ return closeBraceIndex === -1 ? statementText.slice(openBraceIndex + 1) : statementText.slice(openBraceIndex + 1, closeBraceIndex);
65
+ };
66
+ const TYPE_BROWSER_TOOL_SPECIFIER_PATTERN = /\btype\s+browserTool\b/;
67
+ const BROWSER_TOOL_NAME_PATTERN = /\bbrowserTool\b/;
68
+ const SANDBOX_BROWSER_TOOL_FALLBACK_PATTERN = /import\s+\{[^}]*\bbrowserTool\b[^}]*\}\s+from\s+["']@lunora\/agent(?:\/sandbox)?["']/;
69
+ const isValueBrowserToolImport = (statementText) => {
70
+ if (TYPE_ONLY_IMPORT_PATTERN.test(statementText)) {
71
+ return false;
72
+ }
73
+ const specifierList = extractImportSpecifierList(statementText);
74
+ return BROWSER_TOOL_NAME_PATTERN.test(specifierList) && !TYPE_BROWSER_TOOL_SPECIFIER_PATTERN.test(specifierList);
75
+ };
76
+ const hasSandboxBrowserToolImport = (code) => {
77
+ try {
78
+ const [imports] = parse(code);
79
+ return imports.some(
80
+ (entry) => entry.n !== void 0 && SANDBOX_MODULE_SPECIFIERS.has(entry.n) && isValueBrowserToolImport(code.slice(entry.ss, entry.se))
81
+ );
82
+ } catch {
83
+ return SANDBOX_BROWSER_TOOL_FALLBACK_PATTERN.test(code);
84
+ }
85
+ };
58
86
  const CAPABILITY_SOURCES = {
59
87
  usesAi: { pattern: /\bfrom\s+["']@lunora\/ai["']/, source: "@lunora/ai" },
60
88
  usesAnalytics: { pattern: /\bfrom\s+["']@lunora\/bindings\/analytics["']/, source: "@lunora/bindings/analytics" },
@@ -135,9 +163,6 @@ const capabilitiesFromSource = (code) => {
135
163
  ...NO_CAPABILITIES,
136
164
  needsD1: ENV_DB_PATTERN.test(code),
137
165
  usesAi: ENV_AI_PATTERN.test(code),
138
- // A sandbox `browserTool` import provisions BROWSER even without a direct
139
- // `@lunora/browser` import (the browser op runs on the dispatcher's ctx).
140
- usesBrowser: SANDBOX_BROWSER_TOOL_PATTERN.test(code),
141
166
  usesPipelines: CTX_PIPELINES_PATTERN.test(code)
142
167
  });
143
168
  };
@@ -198,81 +223,39 @@ const detectExportedDurableObjects = (entryPath) => {
198
223
  };
199
224
  });
200
225
  };
201
- const CONTAINERS_STAR_REEXPORT_PATTERN = /\bexport\s*\*\s*from\s*["'][^"']*_generated\/containers(?:\.js)?["']/;
202
- const detectContainerExports = (entryPath, containers) => {
203
- if (containers.length === 0) {
204
- return [];
205
- }
206
- if (entryPath === void 0) {
207
- return containers.map((container) => {
208
- return { ...container, exported: false };
209
- });
210
- }
211
- const code = readFileSync(entryPath, "utf8");
212
- const starReexport = CONTAINERS_STAR_REEXPORT_PATTERN.test(code);
213
- let exportedNames;
214
- try {
215
- const [, exports] = parse(code);
216
- exportedNames = new Set(exports.map((entry) => entry.n));
217
- } catch {
218
- exportedNames = new Set(
219
- containers.map((container) => container.className).filter((className) => new RegExp(String.raw`\bexport\b[^\n;]*\b${className}\b`).test(code))
220
- );
221
- }
222
- return containers.map((container) => {
223
- return { ...container, exported: starReexport || exportedNames.has(container.className) };
224
- });
225
- };
226
- const WORKFLOWS_STAR_REEXPORT_PATTERN = /\bexport\s*\*\s*from\s*["'][^"']*_generated\/workflows(?:\.js)?["']/;
227
- const detectWorkflowExports = (entryPath, workflows) => {
228
- if (workflows.length === 0) {
229
- return [];
230
- }
231
- if (entryPath === void 0) {
232
- return workflows.map((workflow) => {
233
- return { ...workflow, exported: false };
234
- });
235
- }
236
- const code = readFileSync(entryPath, "utf8");
237
- const starReexport = WORKFLOWS_STAR_REEXPORT_PATTERN.test(code);
238
- let exportedNames;
239
- try {
240
- const [, exports] = parse(code);
241
- exportedNames = new Set(exports.map((entry) => entry.n));
242
- } catch {
243
- exportedNames = new Set(
244
- workflows.map((workflow) => workflow.className).filter((className) => new RegExp(String.raw`\bexport\b[^\n;]*\b${className}\b`).test(code))
245
- );
246
- }
247
- return workflows.map((workflow) => {
248
- return { ...workflow, exported: starReexport || exportedNames.has(workflow.className) };
249
- });
250
- };
251
- const AGENTS_STAR_REEXPORT_PATTERN = /\bexport\s*\*\s*from\s*["'][^"']*_generated\/agents(?:\.js)?["']/;
252
- const detectAgentExports = (entryPath, agents) => {
253
- if (agents.length === 0) {
226
+ const isTypeOnlyClassExport = (code, className) => (
227
+ // `export type Foo` / `export type { … Foo … }` / `export { type Foo }` — all
228
+ // three type-only forms list the name via the lexer but compile away.
229
+ new RegExp(String.raw`\bexport\s+type\s+${className}\b`).test(code) || new RegExp(String.raw`\bexport\s+type\s*\{[^}]*\b${className}\b`).test(code) || new RegExp(String.raw`\bexport\s+\{[^}]*\btype\s+${className}\b`).test(code)
230
+ );
231
+ const detectClassExports = (entryPath, definitions, generatedModule) => {
232
+ if (definitions.length === 0) {
254
233
  return [];
255
234
  }
256
235
  if (entryPath === void 0) {
257
- return agents.map((agent) => {
258
- return { ...agent, exported: false };
236
+ return definitions.map((definition) => {
237
+ return { ...definition, exported: false };
259
238
  });
260
239
  }
261
240
  const code = readFileSync(entryPath, "utf8");
262
- const starReexport = AGENTS_STAR_REEXPORT_PATTERN.test(code);
241
+ const starReexport = new RegExp(String.raw`\bexport\s*\*\s*from\s*["'][^"']*_generated\/${generatedModule}(?:\.js)?["']`).test(code);
263
242
  let exportedNames;
264
243
  try {
265
244
  const [, exports] = parse(code);
266
245
  exportedNames = new Set(exports.map((entry) => entry.n));
267
246
  } catch {
268
247
  exportedNames = new Set(
269
- agents.map((agent) => agent.className).filter((className) => new RegExp(String.raw`\bexport\b[^\n;]*\b${className}\b`).test(code))
248
+ definitions.map((definition) => definition.className).filter((className) => new RegExp(String.raw`\bexport\b[^\n;]*\b${className}\b`).test(code))
270
249
  );
271
250
  }
272
- return agents.map((agent) => {
273
- return { ...agent, exported: starReexport || exportedNames.has(agent.className) };
251
+ return definitions.map((definition) => {
252
+ const exported = starReexport || exportedNames.has(definition.className) && !isTypeOnlyClassExport(code, definition.className);
253
+ return { ...definition, exported };
274
254
  });
275
255
  };
256
+ const detectContainerExports = (entryPath, containers) => detectClassExports(entryPath, containers, "containers");
257
+ const detectWorkflowExports = (entryPath, workflows) => detectClassExports(entryPath, workflows, "workflows");
258
+ const detectAgentExports = (entryPath, agents) => detectClassExports(entryPath, agents, "agents");
276
259
  const schemaNeedsD1 = (projectRoot, schemaDirectory) => discoverSchemaInfo(projectRoot, schemaDirectory).info?.hasGlobalTable ?? false;
277
260
  const scanCapabilities = (projectRoot, scanDirectories) => {
278
261
  let merged = NO_CAPABILITIES;
@@ -289,6 +272,15 @@ const scanCapabilities = (projectRoot, scanDirectories) => {
289
272
  }
290
273
  return merged;
291
274
  };
275
+ const scanSandboxBrowserToolUsage = (projectRoot, lunoraDirectory) => {
276
+ const absolute = join(projectRoot, lunoraDirectory);
277
+ if (!existsSync(absolute) || !statSync(absolute).isDirectory()) {
278
+ return false;
279
+ }
280
+ const files = [];
281
+ collectSourceFiles(absolute, files);
282
+ return files.some((file) => hasSandboxBrowserToolImport(readFileSync(file, "utf8")));
283
+ };
292
284
  const describeDeclaredExports = (containers, workflows, agents) => [
293
285
  ...containers.map(
294
286
  (container) => container.exported ? `${container.bindingName}/${container.className} (container "${container.exportName}" declared and exported)` : `hint: container "${container.exportName}" is declared but ${container.className} is not exported by the worker entry — add \`export * from "./lunora/_generated/containers"\``
@@ -355,7 +347,11 @@ const inferLunoraBindings = async (options) => {
355
347
  await init;
356
348
  const schemaDirectory = options.schemaDir ?? "lunora";
357
349
  const scanDirectories = options.scanDirs ?? DEFAULT_SCAN_DIRECTORIES;
358
- const capabilities = scanCapabilities(options.projectRoot, scanDirectories);
350
+ const scannedCapabilities = scanCapabilities(options.projectRoot, scanDirectories);
351
+ const capabilities = {
352
+ ...scannedCapabilities,
353
+ usesBrowser: scannedCapabilities.usesBrowser || scanSandboxBrowserToolUsage(options.projectRoot, schemaDirectory)
354
+ };
359
355
  const entryPath = resolveWorkerEntry(options.projectRoot);
360
356
  const durableObjects = entryPath ? detectExportedDurableObjects(entryPath) : [];
361
357
  const needsD1 = capabilities.needsD1 || schemaNeedsD1(options.projectRoot, schemaDirectory);
@@ -1,9 +1,9 @@
1
1
  import { writeFileSync } from 'node:fs';
2
2
  import { modify, applyEdits } from 'jsonc-parser';
3
3
  import { F as FORMATTING } from './jsonc-edit-SbcD7MAe.mjs';
4
+ import { isCacheEnabled, WORKERS_CACHE_MIN_DATE } from './WORKERS_CACHE_MIN_DATE-CaXbS7CX.mjs';
4
5
  import { findWranglerFile, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
5
6
 
6
- const WORKERS_CACHE_MIN_DATE = "2026-05-01";
7
7
  const reconcileWranglerCompatibilityDate = (projectRoot) => {
8
8
  const wranglerPath = findWranglerFile(projectRoot);
9
9
  if (!wranglerPath) {
@@ -14,10 +14,7 @@ const reconcileWranglerCompatibilityDate = (projectRoot) => {
14
14
  return { changed: false, date: void 0, reason: `failed to parse ${wranglerPath} as JSONC`, wranglerPath };
15
15
  }
16
16
  const currentDate = parsed.compatibility_date ?? "";
17
- const cacheEnabledTopLevel = typeof parsed.cache === "object" && parsed.cache !== null && parsed.cache.enabled === true;
18
- const cacheEnabledInExports = typeof parsed.exports === "object" && parsed.exports !== null && Object.values(parsed.exports).some((entry) => typeof entry === "object" && entry !== null && entry.cache?.enabled === true);
19
- const needsCacheDate = cacheEnabledTopLevel || cacheEnabledInExports;
20
- if (!needsCacheDate) {
17
+ if (!isCacheEnabled(parsed)) {
21
18
  return { changed: false, date: currentDate || void 0, reason: "cache not enabled", wranglerPath };
22
19
  }
23
20
  if (currentDate >= WORKERS_CACHE_MIN_DATE) {
@@ -0,0 +1,29 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { modify, applyEdits } from 'jsonc-parser';
3
+ import { findWranglerFile, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
4
+
5
+ const sameTriggers = (a, b) => a.length === b.length && a.every((value, index) => value === b[index]);
6
+ const reconcileWranglerCrons = (projectRoot, cronTriggers) => {
7
+ const wranglerPath = findWranglerFile(projectRoot);
8
+ if (!wranglerPath) {
9
+ return { changed: false, reason: "wrangler.jsonc not found" };
10
+ }
11
+ const { parsed, text } = readWranglerJsonc(wranglerPath);
12
+ if (parsed === void 0) {
13
+ return { changed: false, reason: `failed to parse ${wranglerPath} as JSONC`, wranglerPath };
14
+ }
15
+ const existing = Array.isArray(parsed.triggers?.crons) ? parsed.triggers.crons.filter((value) => typeof value === "string") : [];
16
+ if (sameTriggers(existing, cronTriggers)) {
17
+ return { changed: false, reason: "triggers.crons already in sync", wranglerPath };
18
+ }
19
+ const edits = modify(text, ["triggers", "crons"], [...cronTriggers], {
20
+ formattingOptions: { insertSpaces: true, tabSize: 4 }
21
+ });
22
+ if (edits.length === 0) {
23
+ return { changed: false, reason: "no structural edit produced", wranglerPath };
24
+ }
25
+ writeFileSync(wranglerPath, applyEdits(text, edits), "utf8");
26
+ return { changed: true, wranglerPath };
27
+ };
28
+
29
+ export { reconcileWranglerCrons };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/config",
3
- "version": "1.0.0-alpha.69",
3
+ "version": "1.0.0-alpha.70",
4
4
  "description": "Internal shared CLI + Vite config layer for Lunora: wrangler.jsonc validation, binding inference, and .dev.vars scaffolding",
5
5
  "keywords": [
6
6
  "bindings",
@@ -50,10 +50,10 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "@lunora/codegen": "1.0.0-alpha.45",
53
+ "@lunora/codegen": "1.0.0-alpha.46",
54
54
  "@lunora/container": "1.0.0-alpha.12",
55
55
  "@lunora/errors": "1.0.0-alpha.5",
56
- "@lunora/seed": "1.0.0-alpha.25",
56
+ "@lunora/seed": "1.0.0-alpha.26",
57
57
  "@visulima/colorize": "2.0.0",
58
58
  "@visulima/find-ai-runner": "1.0.0",
59
59
  "dockerode": "^5.0.1",