@kb-labs/workflow-constants 2.119.0-canary.e120bc0ee → 2.119.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/state-machine.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { JobState, RunState, StepState } from './index'\n\n/**\n * Single source of truth for legal status transitions across the workflow\n * engine. Every status-write call site (engine.ts, worker.ts) must route\n * through `assertTransition` (via StateStore.transitionRun/Job/Step) instead\n * of mutating `.status` directly — this is what turns \"any status can go to\n * any status\" into a checked invariant.\n *\n * See docs/adr and the workflow status audit for the incident this closes:\n * a job could be marked `failed` while its step still sat in\n * `waiting_approval`, because nothing validated that transition was legal.\n */\n\nexport type EntityKind = 'run' | 'job' | 'step'\n\n// ═══════════════════════════════════════════════════════════════════════\n// Transition tables\n// ═══════════════════════════════════════════════════════════════════════\n\nexport const RUN_TRANSITIONS: Record<RunState, readonly RunState[]> = {\n // 'success'/'failed': a run can finish without ever visiting 'running' —\n // e.g. a run whose only job is skipped via `if:` (`skipJob` marks the job\n // success directly and never calls `markJobStarted`, so `run.status` can\n // still be 'queued' by the time `checkRunCompletion` finalizes the run).\n queued: ['running', 'cancelled', 'success', 'failed'],\n running: ['success', 'failed', 'cancelled', 'dlq'],\n success: [],\n failed: [],\n cancelled: [],\n skipped: [],\n dlq: [],\n}\n\nexport const JOB_TRANSITIONS: Record<JobState, readonly JobState[]> = {\n // 'success': `skipJob` treats an `if:`-skipped job as success directly,\n // without ever passing through 'running' (see engine.ts `skipJob`).\n // 'failed': `cleanupStaleRuns` force-fails abandoned jobs that never even\n // started (daemon restarted before they were dequeued).\n queued: ['running', 'cancelled', 'skipped', 'success', 'failed'],\n // 'queued': a running job can be re-parked back to queued mid-execution\n // when its current step legitimately pauses (waiting_child reconciliation\n // resume, gate restart) — not a hard requirement that 'running' only ever\n // moves forward.\n running: ['success', 'failed', 'cancelled', 'interrupted', 'waiting_approval', 'waiting_child', 'queued'],\n // 'failed': a parked job can be force-failed directly, without ever\n // passing through 'running' again — e.g. `failChildInvocation` fails the\n // parent job when its child run was cancelled/not found/itself failed,\n // while the parent job is still sitting in 'waiting_child'.\n waiting_approval: ['queued', 'cancelled', 'failed'],\n waiting_child: ['queued', 'cancelled', 'failed'],\n interrupted: ['queued', 'cancelled'],\n success: [],\n // 'queued': `markJobFailed` schedules a retry after a transient failure —\n // the job comes back as 'queued' for its next attempt. 'failed' here means\n // \"this attempt failed\", not always \"this job is permanently done\"; the\n // caller decides whether to retry before ever reaching a real terminal\n // outcome for the job.\n failed: ['queued'],\n cancelled: [],\n skipped: [],\n}\n\nexport const STEP_TRANSITIONS: Record<StepState, readonly StepState[]> = {\n // 'success': a gate's skip-forward decision marks intervening steps\n // success directly (skipped: true in outputs), without ever running them —\n // mirrors JOB_TRANSITIONS.queued's 'success' for the same reason.\n // 'waiting_approval'/'waiting_child': `builtin:approval` and nested\n // `workflow:` invocation steps never call `markStepStarted` at all (see\n // worker.ts's step loop) — they park straight from 'queued', there's no\n // \"running\" phase to observe for these step kinds.\n queued: ['running', 'skipped', 'cancelled', 'success', 'waiting_approval', 'waiting_child'],\n running: ['success', 'failed', 'waiting_approval', 'waiting_child'],\n waiting_approval: ['success', 'failed'],\n // Reconciliation may restart a parked child-invocation step back to `running`.\n waiting_child: ['success', 'failed', 'running'],\n success: [],\n failed: [],\n cancelled: [],\n skipped: [],\n dlq: [],\n}\n\nconst TRANSITIONS: Record<EntityKind, Record<string, readonly string[]>> = {\n run: RUN_TRANSITIONS,\n job: JOB_TRANSITIONS,\n step: STEP_TRANSITIONS,\n}\n\n// ═══════════════════════════════════════════════════════════════════════\n// Predicates\n// ═══════════════════════════════════════════════════════════════════════\n\n/**\n * Terminal: no legal outgoing transition. The entity is done, one way or\n * another, and nothing should ever flip it again.\n */\nconst TERMINAL_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set(['success', 'failed', 'cancelled', 'skipped', 'dlq']),\n job: new Set(['success', 'failed', 'cancelled', 'skipped']),\n step: new Set(['success', 'failed', 'cancelled', 'skipped', 'dlq']),\n}\n\n/**\n * Parked: not terminal, but also not actively holding an executor slot.\n * Something external (a human approval, a child run finishing, a daemon\n * restart recovery pass) is expected to move it back to `queued`/`running`.\n *\n * This is the status class `cleanupStaleRuns` must never force-fail — that\n * was the root cause of the reported bug (job.status=failed while\n * step.status=waiting_approval).\n */\nconst PARKED_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set([]),\n job: new Set(['waiting_approval', 'waiting_child', 'interrupted']),\n step: new Set(['waiting_approval', 'waiting_child']),\n}\n\n/**\n * Active: currently executing or eligible to be picked up by the next\n * scheduler tick, i.e. genuinely needs a live executor.\n */\nconst ACTIVE_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set(['queued', 'running']),\n job: new Set(['queued', 'running']),\n step: new Set(['queued', 'running']),\n}\n\nexport function isTerminal(state: string, kind: EntityKind): boolean {\n return TERMINAL_STATES[kind].has(state)\n}\n\nexport function isParked(state: string, kind: EntityKind): boolean {\n return PARKED_STATES[kind].has(state)\n}\n\nexport function isActive(state: string, kind: EntityKind): boolean {\n return ACTIVE_STATES[kind].has(state)\n}\n\n// ═══════════════════════════════════════════════════════════════════════\n// Transition validation\n// ═══════════════════════════════════════════════════════════════════════\n\nexport class IllegalStateTransitionError extends Error {\n constructor(\n public readonly kind: EntityKind,\n public readonly from: string,\n public readonly to: string,\n public readonly context?: Record<string, unknown>,\n ) {\n super(`Illegal ${kind} status transition: ${from} → ${to}`)\n this.name = 'IllegalStateTransitionError'\n }\n}\n\nexport interface AssertTransitionOptions {\n /**\n * Bulk-reset escape hatch for replayRun/cleanupStaleRuns-style resets that\n * deliberately move a terminal entity back to `queued` (or similar) outside\n * the normal transition table. Must be passed explicitly and is grep-able\n * by design — never add a silent bypass inside the table itself.\n */\n allowReset?: boolean\n}\n\n/**\n * Throws IllegalStateTransitionError if `to` is not reachable from `from`\n * per the transition table for `kind`. No-ops (does not throw) when\n * `from === to` — idempotent re-writes of the same status are always legal.\n */\nexport function assertTransition(\n kind: EntityKind,\n from: string,\n to: string,\n options: AssertTransitionOptions = {},\n): void {\n if (from === to) {\n return\n }\n if (options.allowReset) {\n return\n }\n const legal = TRANSITIONS[kind][from]\n if (!legal || !legal.includes(to)) {\n throw new IllegalStateTransitionError(kind, from, to)\n }\n}\n","const RUN_STATES = ['queued', 'running', 'success', 'failed', 'cancelled', 'skipped', 'dlq'] as const\nconst JOB_STATES = [\n 'queued', 'running', 'success', 'failed', 'cancelled', 'skipped', 'interrupted',\n 'waiting_approval', 'waiting_child',\n] as const\nconst STEP_STATES = [...RUN_STATES, 'waiting_approval', 'waiting_child'] as const\nconst JOB_PRIORITIES = ['high', 'normal', 'low'] as const\n\nexport { RUN_STATES, JOB_STATES, STEP_STATES, JOB_PRIORITIES }\n\nexport type RunState = (typeof RUN_STATES)[number]\nexport type JobState = (typeof JOB_STATES)[number]\nexport type StepState = (typeof STEP_STATES)[number]\nexport type JobPriority = (typeof JOB_PRIORITIES)[number]\n\nexport {\n RUN_TRANSITIONS,\n JOB_TRANSITIONS,\n STEP_TRANSITIONS,\n isTerminal,\n isParked,\n isActive,\n assertTransition,\n IllegalStateTransitionError,\n} from './state-machine'\nexport type { EntityKind, AssertTransitionOptions } from './state-machine'\n\nexport const EVENT_NAMES = {\n run: {\n created: 'run.created',\n started: 'run.started',\n updated: 'run.updated',\n finished: 'run.finished',\n cancelled: 'run.cancelled',\n failed: 'run.failed',\n },\n job: {\n queued: 'job.queued',\n started: 'job.started',\n updated: 'job.updated',\n succeeded: 'job.succeeded',\n failed: 'job.failed',\n cancelled: 'job.cancelled',\n skipped: 'job.skipped',\n },\n step: {\n queued: 'step.queued',\n started: 'step.started',\n updated: 'step.updated',\n succeeded: 'step.succeeded',\n failed: 'step.failed',\n cancelled: 'step.cancelled',\n skipped: 'step.skipped',\n waitingApproval: 'step.waitingApproval',\n waitingChild: 'step.waitingChild',\n },\n log: {\n appended: 'log.appended',\n },\n} as const\n\nexport type WorkflowEventName =\n | (typeof EVENT_NAMES)['run'][keyof (typeof EVENT_NAMES)['run']]\n | (typeof EVENT_NAMES)['job'][keyof (typeof EVENT_NAMES)['job']]\n | (typeof EVENT_NAMES)['step'][keyof (typeof EVENT_NAMES)['step']]\n | (typeof EVENT_NAMES)['log'][keyof (typeof EVENT_NAMES)['log']]\n\nexport interface RedisKeyFactory {\n namespace: string\n idempotency(key: string): string\n concurrency(group: string): string\n run(runId: string): string\n artifacts(runId: string): string\n jobQueue(priority?: JobPriority): string\n runEvents(runId: string): string\n eventChannel(): string\n lock(name: string): string\n}\n\nexport interface RedisKeyFactoryOptions {\n namespace?: string\n}\n\nexport const DEFAULT_REDIS_NAMESPACE = 'kb'\nexport const WORKFLOW_REDIS_CHANNEL = 'kb:wf:events'\n\nexport function createRedisKeyFactory(\n options: RedisKeyFactoryOptions = {},\n): RedisKeyFactory {\n const namespace =\n options.namespace?.replace(/[:\\s]+/g, ':').replace(/:+$/, '') ||\n DEFAULT_REDIS_NAMESPACE\n const wfNs = `${namespace}:wf`\n\n return {\n namespace: wfNs,\n idempotency(key: string) {\n return `${wfNs}:idemp:${key}`\n },\n concurrency(group: string) {\n return `${wfNs}:conc:${group}`\n },\n run(runId: string) {\n return `${wfNs}:runs:${runId}`\n },\n artifacts(runId: string) {\n return `${wfNs}:artifacts:${runId}`\n },\n jobQueue(priority: JobPriority = 'normal') {\n return `${wfNs}:queue:jobs:${priority}`\n },\n runEvents(runId: string) {\n return `${wfNs}:events:runs:${runId}`\n },\n eventChannel() {\n return WORKFLOW_REDIS_CHANNEL\n },\n lock(name: string) {\n return `${wfNs}:locks:${name}`\n },\n }\n}\n\nexport const IDEMPOTENCY_TTL_ENV = 'KB_WF_IDEMP_TTL_MS'\nexport const CONCURRENCY_TTL_ENV = 'KB_WF_CONC_TTL_MS'\nexport const REDIS_URL_ENV = 'KB_REDIS_URL'\nexport const REDIS_MODE_ENV = 'KB_REDIS_MODE'\nexport const REDIS_NAMESPACE_ENV = 'KB_REDIS_NAMESPACE'\n\nexport type RedisMode = 'standalone' | 'cluster' | 'sentinel'\n\n\n"]}
1
+ {"version":3,"sources":["../../home/runner/work/kb-labs/kb-labs/plugins/workflow/constants/src/state-machine.ts","../../home/runner/work/kb-labs/kb-labs/plugins/workflow/constants/src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { JobState, RunState, StepState } from './index'\n\n/**\n * Single source of truth for legal status transitions across the workflow\n * engine. Every status-write call site (engine.ts, worker.ts) must route\n * through `assertTransition` (via StateStore.transitionRun/Job/Step) instead\n * of mutating `.status` directly — this is what turns \"any status can go to\n * any status\" into a checked invariant.\n *\n * See docs/adr and the workflow status audit for the incident this closes:\n * a job could be marked `failed` while its step still sat in\n * `waiting_approval`, because nothing validated that transition was legal.\n */\n\nexport type EntityKind = 'run' | 'job' | 'step'\n\n// ═══════════════════════════════════════════════════════════════════════\n// Transition tables\n// ═══════════════════════════════════════════════════════════════════════\n\nexport const RUN_TRANSITIONS: Record<RunState, readonly RunState[]> = {\n // 'success'/'failed': a run can finish without ever visiting 'running' —\n // e.g. a run whose only job is skipped via `if:` (`skipJob` marks the job\n // success directly and never calls `markJobStarted`, so `run.status` can\n // still be 'queued' by the time `checkRunCompletion` finalizes the run).\n queued: ['running', 'cancelled', 'success', 'failed'],\n running: ['success', 'failed', 'cancelled', 'dlq'],\n success: [],\n failed: [],\n cancelled: [],\n skipped: [],\n dlq: [],\n}\n\nexport const JOB_TRANSITIONS: Record<JobState, readonly JobState[]> = {\n // 'success': `skipJob` treats an `if:`-skipped job as success directly,\n // without ever passing through 'running' (see engine.ts `skipJob`).\n // 'failed': `cleanupStaleRuns` force-fails abandoned jobs that never even\n // started (daemon restarted before they were dequeued).\n queued: ['running', 'cancelled', 'skipped', 'success', 'failed'],\n // 'queued': a running job can be re-parked back to queued mid-execution\n // when its current step legitimately pauses (waiting_child reconciliation\n // resume, gate restart) — not a hard requirement that 'running' only ever\n // moves forward.\n running: ['success', 'failed', 'cancelled', 'interrupted', 'waiting_approval', 'waiting_child', 'queued'],\n // 'failed': a parked job can be force-failed directly, without ever\n // passing through 'running' again — e.g. `failChildInvocation` fails the\n // parent job when its child run was cancelled/not found/itself failed,\n // while the parent job is still sitting in 'waiting_child'.\n waiting_approval: ['queued', 'cancelled', 'failed'],\n waiting_child: ['queued', 'cancelled', 'failed'],\n interrupted: ['queued', 'cancelled'],\n success: [],\n // 'queued': `markJobFailed` schedules a retry after a transient failure —\n // the job comes back as 'queued' for its next attempt. 'failed' here means\n // \"this attempt failed\", not always \"this job is permanently done\"; the\n // caller decides whether to retry before ever reaching a real terminal\n // outcome for the job.\n failed: ['queued'],\n cancelled: [],\n skipped: [],\n}\n\nexport const STEP_TRANSITIONS: Record<StepState, readonly StepState[]> = {\n // 'success': a gate's skip-forward decision marks intervening steps\n // success directly (skipped: true in outputs), without ever running them —\n // mirrors JOB_TRANSITIONS.queued's 'success' for the same reason.\n // 'waiting_approval'/'waiting_child': `builtin:approval` and nested\n // `workflow:` invocation steps never call `markStepStarted` at all (see\n // worker.ts's step loop) — they park straight from 'queued', there's no\n // \"running\" phase to observe for these step kinds.\n queued: ['running', 'skipped', 'cancelled', 'success', 'waiting_approval', 'waiting_child'],\n running: ['success', 'failed', 'waiting_approval', 'waiting_child'],\n waiting_approval: ['success', 'failed'],\n // Reconciliation may restart a parked child-invocation step back to `running`.\n waiting_child: ['success', 'failed', 'running'],\n success: [],\n failed: [],\n cancelled: [],\n skipped: [],\n dlq: [],\n}\n\nconst TRANSITIONS: Record<EntityKind, Record<string, readonly string[]>> = {\n run: RUN_TRANSITIONS,\n job: JOB_TRANSITIONS,\n step: STEP_TRANSITIONS,\n}\n\n// ═══════════════════════════════════════════════════════════════════════\n// Predicates\n// ═══════════════════════════════════════════════════════════════════════\n\n/**\n * Terminal: no legal outgoing transition. The entity is done, one way or\n * another, and nothing should ever flip it again.\n */\nconst TERMINAL_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set(['success', 'failed', 'cancelled', 'skipped', 'dlq']),\n job: new Set(['success', 'failed', 'cancelled', 'skipped']),\n step: new Set(['success', 'failed', 'cancelled', 'skipped', 'dlq']),\n}\n\n/**\n * Parked: not terminal, but also not actively holding an executor slot.\n * Something external (a human approval, a child run finishing, a daemon\n * restart recovery pass) is expected to move it back to `queued`/`running`.\n *\n * This is the status class `cleanupStaleRuns` must never force-fail — that\n * was the root cause of the reported bug (job.status=failed while\n * step.status=waiting_approval).\n */\nconst PARKED_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set([]),\n job: new Set(['waiting_approval', 'waiting_child', 'interrupted']),\n step: new Set(['waiting_approval', 'waiting_child']),\n}\n\n/**\n * Active: currently executing or eligible to be picked up by the next\n * scheduler tick, i.e. genuinely needs a live executor.\n */\nconst ACTIVE_STATES: Record<EntityKind, ReadonlySet<string>> = {\n run: new Set(['queued', 'running']),\n job: new Set(['queued', 'running']),\n step: new Set(['queued', 'running']),\n}\n\nexport function isTerminal(state: string, kind: EntityKind): boolean {\n return TERMINAL_STATES[kind].has(state)\n}\n\nexport function isParked(state: string, kind: EntityKind): boolean {\n return PARKED_STATES[kind].has(state)\n}\n\nexport function isActive(state: string, kind: EntityKind): boolean {\n return ACTIVE_STATES[kind].has(state)\n}\n\n// ═══════════════════════════════════════════════════════════════════════\n// Transition validation\n// ═══════════════════════════════════════════════════════════════════════\n\nexport class IllegalStateTransitionError extends Error {\n constructor(\n public readonly kind: EntityKind,\n public readonly from: string,\n public readonly to: string,\n public readonly context?: Record<string, unknown>,\n ) {\n super(`Illegal ${kind} status transition: ${from} → ${to}`)\n this.name = 'IllegalStateTransitionError'\n }\n}\n\nexport interface AssertTransitionOptions {\n /**\n * Bulk-reset escape hatch for replayRun/cleanupStaleRuns-style resets that\n * deliberately move a terminal entity back to `queued` (or similar) outside\n * the normal transition table. Must be passed explicitly and is grep-able\n * by design — never add a silent bypass inside the table itself.\n */\n allowReset?: boolean\n}\n\n/**\n * Throws IllegalStateTransitionError if `to` is not reachable from `from`\n * per the transition table for `kind`. No-ops (does not throw) when\n * `from === to` — idempotent re-writes of the same status are always legal.\n */\nexport function assertTransition(\n kind: EntityKind,\n from: string,\n to: string,\n options: AssertTransitionOptions = {},\n): void {\n if (from === to) {\n return\n }\n if (options.allowReset) {\n return\n }\n const legal = TRANSITIONS[kind][from]\n if (!legal || !legal.includes(to)) {\n throw new IllegalStateTransitionError(kind, from, to)\n }\n}\n","const RUN_STATES = ['queued', 'running', 'success', 'failed', 'cancelled', 'skipped', 'dlq'] as const\nconst JOB_STATES = [\n 'queued', 'running', 'success', 'failed', 'cancelled', 'skipped', 'interrupted',\n 'waiting_approval', 'waiting_child',\n] as const\nconst STEP_STATES = [...RUN_STATES, 'waiting_approval', 'waiting_child'] as const\nconst JOB_PRIORITIES = ['high', 'normal', 'low'] as const\n\nexport { RUN_STATES, JOB_STATES, STEP_STATES, JOB_PRIORITIES }\n\nexport type RunState = (typeof RUN_STATES)[number]\nexport type JobState = (typeof JOB_STATES)[number]\nexport type StepState = (typeof STEP_STATES)[number]\nexport type JobPriority = (typeof JOB_PRIORITIES)[number]\n\nexport {\n RUN_TRANSITIONS,\n JOB_TRANSITIONS,\n STEP_TRANSITIONS,\n isTerminal,\n isParked,\n isActive,\n assertTransition,\n IllegalStateTransitionError,\n} from './state-machine'\nexport type { EntityKind, AssertTransitionOptions } from './state-machine'\n\nexport const EVENT_NAMES = {\n run: {\n created: 'run.created',\n started: 'run.started',\n updated: 'run.updated',\n finished: 'run.finished',\n cancelled: 'run.cancelled',\n failed: 'run.failed',\n },\n job: {\n queued: 'job.queued',\n started: 'job.started',\n updated: 'job.updated',\n succeeded: 'job.succeeded',\n failed: 'job.failed',\n cancelled: 'job.cancelled',\n skipped: 'job.skipped',\n },\n step: {\n queued: 'step.queued',\n started: 'step.started',\n updated: 'step.updated',\n succeeded: 'step.succeeded',\n failed: 'step.failed',\n cancelled: 'step.cancelled',\n skipped: 'step.skipped',\n waitingApproval: 'step.waitingApproval',\n waitingChild: 'step.waitingChild',\n },\n log: {\n appended: 'log.appended',\n },\n} as const\n\nexport type WorkflowEventName =\n | (typeof EVENT_NAMES)['run'][keyof (typeof EVENT_NAMES)['run']]\n | (typeof EVENT_NAMES)['job'][keyof (typeof EVENT_NAMES)['job']]\n | (typeof EVENT_NAMES)['step'][keyof (typeof EVENT_NAMES)['step']]\n | (typeof EVENT_NAMES)['log'][keyof (typeof EVENT_NAMES)['log']]\n\nexport interface RedisKeyFactory {\n namespace: string\n idempotency(key: string): string\n concurrency(group: string): string\n run(runId: string): string\n artifacts(runId: string): string\n jobQueue(priority?: JobPriority): string\n runEvents(runId: string): string\n eventChannel(): string\n lock(name: string): string\n}\n\nexport interface RedisKeyFactoryOptions {\n namespace?: string\n}\n\nexport const DEFAULT_REDIS_NAMESPACE = 'kb'\nexport const WORKFLOW_REDIS_CHANNEL = 'kb:wf:events'\n\nexport function createRedisKeyFactory(\n options: RedisKeyFactoryOptions = {},\n): RedisKeyFactory {\n const namespace =\n options.namespace?.replace(/[:\\s]+/g, ':').replace(/:+$/, '') ||\n DEFAULT_REDIS_NAMESPACE\n const wfNs = `${namespace}:wf`\n\n return {\n namespace: wfNs,\n idempotency(key: string) {\n return `${wfNs}:idemp:${key}`\n },\n concurrency(group: string) {\n return `${wfNs}:conc:${group}`\n },\n run(runId: string) {\n return `${wfNs}:runs:${runId}`\n },\n artifacts(runId: string) {\n return `${wfNs}:artifacts:${runId}`\n },\n jobQueue(priority: JobPriority = 'normal') {\n return `${wfNs}:queue:jobs:${priority}`\n },\n runEvents(runId: string) {\n return `${wfNs}:events:runs:${runId}`\n },\n eventChannel() {\n return WORKFLOW_REDIS_CHANNEL\n },\n lock(name: string) {\n return `${wfNs}:locks:${name}`\n },\n }\n}\n\nexport const IDEMPOTENCY_TTL_ENV = 'KB_WF_IDEMP_TTL_MS'\nexport const CONCURRENCY_TTL_ENV = 'KB_WF_CONC_TTL_MS'\nexport const REDIS_URL_ENV = 'KB_REDIS_URL'\nexport const REDIS_MODE_ENV = 'KB_REDIS_MODE'\nexport const REDIS_NAMESPACE_ENV = 'KB_REDIS_NAMESPACE'\n\nexport type RedisMode = 'standalone' | 'cluster' | 'sentinel'\n\n\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kb-labs/workflow-constants",
3
3
  "description": "Shared constants for the KB Labs workflow engine.",
4
- "version": "2.119.0-canary.e120bc0ee",
4
+ "version": "2.119.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -26,10 +26,10 @@
26
26
  "tsup": "^8.5.0",
27
27
  "typescript": "^5.6.3",
28
28
  "vitest": "^3.2.6",
29
- "@kb-labs/devkit": "2.119.0-canary.e120bc0ee"
29
+ "@kb-labs/devkit": "2.119.0"
30
30
  },
31
31
  "engines": {
32
- "node": ">=22.0.0",
32
+ "node": ">=24.0.0",
33
33
  "pnpm": ">=9.0.0"
34
34
  },
35
35
  "sideEffects": false,