@lunora/config 1.0.0-alpha.46 → 1.0.0-alpha.47
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 +131 -1
- package/dist/index.d.ts +131 -1
- package/dist/index.mjs +3 -1
- package/dist/packem_shared/AGENT_MODE_ENV-DM1Siczo.mjs +17 -0
- package/dist/packem_shared/DEV_DAEMON_ENV-FIEtW7Fz.mjs +163 -0
- package/dist/packem_shared/{detectFramework-Br-BcPBq.mjs → detectFramework-U08038Yp.mjs} +3 -3
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,23 @@ export type { ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
|
3
3
|
import { Writable } from 'node:stream';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-DCmwn7zQ.mjs";
|
|
6
|
+
/** Minimal env shape — `process.env` structurally, injectable for tests. */
|
|
7
|
+
type EnvLike = Readonly<Record<string, string | undefined>>;
|
|
8
|
+
/** One detected agent: which tool, and which env var gave it away. */
|
|
9
|
+
interface AgentDetection {
|
|
10
|
+
/** Human-readable agent name, for the "agent detected" log line. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** The environment variable that matched. */
|
|
13
|
+
variable: string;
|
|
14
|
+
}
|
|
15
|
+
/** Env var that forces agent mode on (`1`/`true`) or off (`0`/`false`), overriding detection. */
|
|
16
|
+
declare const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
|
|
17
|
+
/**
|
|
18
|
+
* Detect the AI agent driving this process, or `undefined` when none is.
|
|
19
|
+
* `LUNORA_AGENT_MODE` wins over `@visulima/find-ai-runner`'s marker table in
|
|
20
|
+
* both directions. Pure — pass a custom `env` in tests.
|
|
21
|
+
*/
|
|
22
|
+
declare const detectAiAgent: (env?: EnvLike) => AgentDetection | undefined;
|
|
6
23
|
/**
|
|
7
24
|
* Project-relative directory the Lunora agent skills ("rules") install into.
|
|
8
25
|
* This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
|
|
@@ -157,6 +174,13 @@ interface FrameworkDetection {
|
|
|
157
174
|
framework: DetectedFramework;
|
|
158
175
|
}
|
|
159
176
|
/**
|
|
177
|
+
* Read and parse the project `package.json`, returning its merged
|
|
178
|
+
* `dependencies` + `devDependencies` name set (empty on any failure). Public
|
|
179
|
+
* so sibling consumers (e.g. the CLI's Vite-project detection) share one
|
|
180
|
+
* best-effort reader instead of re-parsing `package.json` themselves.
|
|
181
|
+
*/
|
|
182
|
+
declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
|
|
183
|
+
/**
|
|
160
184
|
* Detect which meta-framework a project uses by inspecting its `package.json`
|
|
161
185
|
* dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
|
|
162
186
|
*
|
|
@@ -165,6 +189,112 @@ interface FrameworkDetection {
|
|
|
165
189
|
* SPA flow is preserved.
|
|
166
190
|
*/
|
|
167
191
|
declare const detectFramework: (root: string) => FrameworkDetection;
|
|
192
|
+
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
193
|
+
declare const DEV_STATE_DIR = ".lunora";
|
|
194
|
+
/** The dev-server state filename, relative to the project root. */
|
|
195
|
+
declare const DEV_STATE_FILE: string;
|
|
196
|
+
/** Log file a backgrounded dev server's output is captured to, relative to the project root. */
|
|
197
|
+
declare const DEV_LOG_FILE: string;
|
|
198
|
+
/**
|
|
199
|
+
* Marker env `lunora dev --background` sets on the detached server process
|
|
200
|
+
* (the daemon `lunora dev` or `vite dev`), so it records itself as
|
|
201
|
+
* `background: true` — and, for the CLI daemon, never re-detects an agent and
|
|
202
|
+
* recurses into background mode again.
|
|
203
|
+
*/
|
|
204
|
+
declare const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
|
|
205
|
+
/** Env carrying the capture-log path into the detached server, recorded in the state file. */
|
|
206
|
+
declare const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
|
|
207
|
+
/**
|
|
208
|
+
* Env carrying the PID of a parent that holds a *provisional* state record it
|
|
209
|
+
* expects the child dev server to supersede. The CLI claims `.lunora/dev.json`
|
|
210
|
+
* with its own PID before spawning the real server (closing the duplicate-start
|
|
211
|
+
* race for the vite flavor and the wrangler daemon), then hands its PID down
|
|
212
|
+
* via this variable; the child's claim (see {@link claimDevServerState}'s
|
|
213
|
+
* `supersedePid`) may replace exactly that record with the authoritative
|
|
214
|
+
* URL + PID.
|
|
215
|
+
*/
|
|
216
|
+
declare const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
|
|
217
|
+
/** How the recorded dev server runs. */
|
|
218
|
+
type DevServerMode = "cli" | "vite";
|
|
219
|
+
/** The state record persisted to `.lunora/dev.json`. */
|
|
220
|
+
interface DevServerState {
|
|
221
|
+
/** Whether the server was detached into the background (`lunora dev --background`). */
|
|
222
|
+
background?: boolean;
|
|
223
|
+
/** Absolute path of the log file capturing the server's output, when captured. */
|
|
224
|
+
logFile?: string;
|
|
225
|
+
/** `"cli"` for the `lunora dev` wrangler orchestration, `"vite"` for a Vite dev server. */
|
|
226
|
+
mode: DevServerMode;
|
|
227
|
+
/** PID of the process to signal for shutdown (the orchestrating CLI or the Vite process). */
|
|
228
|
+
pid: number;
|
|
229
|
+
/** ISO-8601 stamp written at startup, purely informational (drives `status` uptime). */
|
|
230
|
+
startedAt?: string;
|
|
231
|
+
/** The embedded studio server's URL, when it runs. */
|
|
232
|
+
studioUrl?: string;
|
|
233
|
+
/** The primary URL serving the worker/app. */
|
|
234
|
+
url: string;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* True when a process with `pid` is currently alive AND signalable by this
|
|
238
|
+
* user. Signal `0` performs the existence check without delivering anything.
|
|
239
|
+
*
|
|
240
|
+
* `EPERM` ("alive but another user's process") deliberately counts as NOT
|
|
241
|
+
* alive here: every dev server this module tracks was spawned by the current
|
|
242
|
+
* user, so a PID we cannot signal is by definition a recycled PID — treating
|
|
243
|
+
* it as running would wedge the lockfile permanently and aim `dev stop`'s
|
|
244
|
+
* kill escalation at an innocent process.
|
|
245
|
+
*/
|
|
246
|
+
declare const isProcessAlive: (pid: number) => boolean;
|
|
247
|
+
/**
|
|
248
|
+
* True when the record's PID verifiably still refers to the dev server that
|
|
249
|
+
* wrote the record — not merely "some process exists with that number".
|
|
250
|
+
* Guards against PID reuse: a server process necessarily starts BEFORE its
|
|
251
|
+
* record is written, so a process that started after `startedAt` (+ skew) is
|
|
252
|
+
* a recycled PID wearing the corpse's number. The start-time check runs only
|
|
253
|
+
* where the platform exposes it (Linux); elsewhere liveness alone decides.
|
|
254
|
+
*/
|
|
255
|
+
declare const isRecordedProcessCurrent: (state: DevServerState) => boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Read the state record from `.lunora/dev.json`, or `undefined` when there is
|
|
258
|
+
* no usable record. Best-effort; performs NO liveness check — use
|
|
259
|
+
* {@link readLiveDevServerState} for "is a dev server actually running".
|
|
260
|
+
*/
|
|
261
|
+
declare const readDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* Write the state record to `.lunora/dev.json`, creating the `.lunora/`
|
|
264
|
+
* directory when absent. Returns the absolute path written, or `undefined`
|
|
265
|
+
* when the write failed (state is convenience metadata — a read-only checkout
|
|
266
|
+
* must never crash dev startup).
|
|
267
|
+
*/
|
|
268
|
+
declare const writeDevServerState: (projectRoot: string, state: DevServerState) => string | undefined;
|
|
269
|
+
/**
|
|
270
|
+
* Merge `patch` into the existing state record, when one exists. Used by the
|
|
271
|
+
* CLI to stamp `background`/`logFile` onto the record the Vite plugin wrote.
|
|
272
|
+
* Returns the merged record, or `undefined` when there was nothing to update.
|
|
273
|
+
*/
|
|
274
|
+
declare const updateDevServerState: (projectRoot: string, patch: Partial<DevServerState>) => DevServerState | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Remove `.lunora/dev.json`. Idempotent and never throws. When `expectedPid`
|
|
277
|
+
* is given, the file is only removed while it still records that PID — so a
|
|
278
|
+
* shutting-down server can't clobber the record a newer server just wrote.
|
|
279
|
+
*/
|
|
280
|
+
declare const clearDevServerState: (projectRoot: string, expectedPid?: number) => void;
|
|
281
|
+
/**
|
|
282
|
+
* The state record of a dev server that is verifiably running right now, or
|
|
283
|
+
* `undefined`. A record whose PID is dead — or recycled onto a different
|
|
284
|
+
* process (see {@link isRecordedProcessCurrent}) — is stale: it is cleared on
|
|
285
|
+
* the spot so subsequent starts don't keep re-reading a corpse.
|
|
286
|
+
*/
|
|
287
|
+
declare const readLiveDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
288
|
+
/** Result of {@link claimDevServerState}: claimed, or lost to the live server already recorded. */
|
|
289
|
+
interface ClaimDevServerStateResult {
|
|
290
|
+
/** The live record that won the race, when `ok` is `false`. */
|
|
291
|
+
existing?: DevServerState;
|
|
292
|
+
/** Whether this process now owns the record. */
|
|
293
|
+
ok: boolean;
|
|
294
|
+
}
|
|
295
|
+
declare const claimDevServerState: (projectRoot: string, state: DevServerState, options?: {
|
|
296
|
+
supersedePid?: number;
|
|
297
|
+
}) => ClaimDevServerStateResult;
|
|
168
298
|
/**
|
|
169
299
|
* The `.dev.vars` line grammar — one owner, shared by every reader/writer of the
|
|
170
300
|
* file so the format can't drift between packages. `@lunora/cli`'s `env`
|
|
@@ -1319,4 +1449,4 @@ interface WranglerProjectValidationResult {
|
|
|
1319
1449
|
* `{ problems, wranglerPath }` shape plus the structured `report`.
|
|
1320
1450
|
*/
|
|
1321
1451
|
declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
|
|
1322
|
-
export { ACCENT, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, 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 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 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, classifyEdit, createConfirm, detectAgentRules, detectFramework, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readLinkedProject, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, secretsForPackages, streamContainerLogs, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeLinkedProject };
|
|
1452
|
+
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 DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, 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 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, createConfirm, detectAgentRules, detectAiAgent, detectFramework, 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, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,23 @@ export type { ContainerIR, WorkflowIR } from '@lunora/codegen';
|
|
|
3
3
|
import { Writable } from 'node:stream';
|
|
4
4
|
import 'ts-morph';
|
|
5
5
|
export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-DCmwn7zQ.js";
|
|
6
|
+
/** Minimal env shape — `process.env` structurally, injectable for tests. */
|
|
7
|
+
type EnvLike = Readonly<Record<string, string | undefined>>;
|
|
8
|
+
/** One detected agent: which tool, and which env var gave it away. */
|
|
9
|
+
interface AgentDetection {
|
|
10
|
+
/** Human-readable agent name, for the "agent detected" log line. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** The environment variable that matched. */
|
|
13
|
+
variable: string;
|
|
14
|
+
}
|
|
15
|
+
/** Env var that forces agent mode on (`1`/`true`) or off (`0`/`false`), overriding detection. */
|
|
16
|
+
declare const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
|
|
17
|
+
/**
|
|
18
|
+
* Detect the AI agent driving this process, or `undefined` when none is.
|
|
19
|
+
* `LUNORA_AGENT_MODE` wins over `@visulima/find-ai-runner`'s marker table in
|
|
20
|
+
* both directions. Pure — pass a custom `env` in tests.
|
|
21
|
+
*/
|
|
22
|
+
declare const detectAiAgent: (env?: EnvLike) => AgentDetection | undefined;
|
|
6
23
|
/**
|
|
7
24
|
* Project-relative directory the Lunora agent skills ("rules") install into.
|
|
8
25
|
* This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
|
|
@@ -157,6 +174,13 @@ interface FrameworkDetection {
|
|
|
157
174
|
framework: DetectedFramework;
|
|
158
175
|
}
|
|
159
176
|
/**
|
|
177
|
+
* Read and parse the project `package.json`, returning its merged
|
|
178
|
+
* `dependencies` + `devDependencies` name set (empty on any failure). Public
|
|
179
|
+
* so sibling consumers (e.g. the CLI's Vite-project detection) share one
|
|
180
|
+
* best-effort reader instead of re-parsing `package.json` themselves.
|
|
181
|
+
*/
|
|
182
|
+
declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
|
|
183
|
+
/**
|
|
160
184
|
* Detect which meta-framework a project uses by inspecting its `package.json`
|
|
161
185
|
* dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
|
|
162
186
|
*
|
|
@@ -165,6 +189,112 @@ interface FrameworkDetection {
|
|
|
165
189
|
* SPA flow is preserved.
|
|
166
190
|
*/
|
|
167
191
|
declare const detectFramework: (root: string) => FrameworkDetection;
|
|
192
|
+
/** Directory holding per-checkout Lunora state (gitignored by convention). */
|
|
193
|
+
declare const DEV_STATE_DIR = ".lunora";
|
|
194
|
+
/** The dev-server state filename, relative to the project root. */
|
|
195
|
+
declare const DEV_STATE_FILE: string;
|
|
196
|
+
/** Log file a backgrounded dev server's output is captured to, relative to the project root. */
|
|
197
|
+
declare const DEV_LOG_FILE: string;
|
|
198
|
+
/**
|
|
199
|
+
* Marker env `lunora dev --background` sets on the detached server process
|
|
200
|
+
* (the daemon `lunora dev` or `vite dev`), so it records itself as
|
|
201
|
+
* `background: true` — and, for the CLI daemon, never re-detects an agent and
|
|
202
|
+
* recurses into background mode again.
|
|
203
|
+
*/
|
|
204
|
+
declare const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
|
|
205
|
+
/** Env carrying the capture-log path into the detached server, recorded in the state file. */
|
|
206
|
+
declare const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
|
|
207
|
+
/**
|
|
208
|
+
* Env carrying the PID of a parent that holds a *provisional* state record it
|
|
209
|
+
* expects the child dev server to supersede. The CLI claims `.lunora/dev.json`
|
|
210
|
+
* with its own PID before spawning the real server (closing the duplicate-start
|
|
211
|
+
* race for the vite flavor and the wrangler daemon), then hands its PID down
|
|
212
|
+
* via this variable; the child's claim (see {@link claimDevServerState}'s
|
|
213
|
+
* `supersedePid`) may replace exactly that record with the authoritative
|
|
214
|
+
* URL + PID.
|
|
215
|
+
*/
|
|
216
|
+
declare const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
|
|
217
|
+
/** How the recorded dev server runs. */
|
|
218
|
+
type DevServerMode = "cli" | "vite";
|
|
219
|
+
/** The state record persisted to `.lunora/dev.json`. */
|
|
220
|
+
interface DevServerState {
|
|
221
|
+
/** Whether the server was detached into the background (`lunora dev --background`). */
|
|
222
|
+
background?: boolean;
|
|
223
|
+
/** Absolute path of the log file capturing the server's output, when captured. */
|
|
224
|
+
logFile?: string;
|
|
225
|
+
/** `"cli"` for the `lunora dev` wrangler orchestration, `"vite"` for a Vite dev server. */
|
|
226
|
+
mode: DevServerMode;
|
|
227
|
+
/** PID of the process to signal for shutdown (the orchestrating CLI or the Vite process). */
|
|
228
|
+
pid: number;
|
|
229
|
+
/** ISO-8601 stamp written at startup, purely informational (drives `status` uptime). */
|
|
230
|
+
startedAt?: string;
|
|
231
|
+
/** The embedded studio server's URL, when it runs. */
|
|
232
|
+
studioUrl?: string;
|
|
233
|
+
/** The primary URL serving the worker/app. */
|
|
234
|
+
url: string;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* True when a process with `pid` is currently alive AND signalable by this
|
|
238
|
+
* user. Signal `0` performs the existence check without delivering anything.
|
|
239
|
+
*
|
|
240
|
+
* `EPERM` ("alive but another user's process") deliberately counts as NOT
|
|
241
|
+
* alive here: every dev server this module tracks was spawned by the current
|
|
242
|
+
* user, so a PID we cannot signal is by definition a recycled PID — treating
|
|
243
|
+
* it as running would wedge the lockfile permanently and aim `dev stop`'s
|
|
244
|
+
* kill escalation at an innocent process.
|
|
245
|
+
*/
|
|
246
|
+
declare const isProcessAlive: (pid: number) => boolean;
|
|
247
|
+
/**
|
|
248
|
+
* True when the record's PID verifiably still refers to the dev server that
|
|
249
|
+
* wrote the record — not merely "some process exists with that number".
|
|
250
|
+
* Guards against PID reuse: a server process necessarily starts BEFORE its
|
|
251
|
+
* record is written, so a process that started after `startedAt` (+ skew) is
|
|
252
|
+
* a recycled PID wearing the corpse's number. The start-time check runs only
|
|
253
|
+
* where the platform exposes it (Linux); elsewhere liveness alone decides.
|
|
254
|
+
*/
|
|
255
|
+
declare const isRecordedProcessCurrent: (state: DevServerState) => boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Read the state record from `.lunora/dev.json`, or `undefined` when there is
|
|
258
|
+
* no usable record. Best-effort; performs NO liveness check — use
|
|
259
|
+
* {@link readLiveDevServerState} for "is a dev server actually running".
|
|
260
|
+
*/
|
|
261
|
+
declare const readDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* Write the state record to `.lunora/dev.json`, creating the `.lunora/`
|
|
264
|
+
* directory when absent. Returns the absolute path written, or `undefined`
|
|
265
|
+
* when the write failed (state is convenience metadata — a read-only checkout
|
|
266
|
+
* must never crash dev startup).
|
|
267
|
+
*/
|
|
268
|
+
declare const writeDevServerState: (projectRoot: string, state: DevServerState) => string | undefined;
|
|
269
|
+
/**
|
|
270
|
+
* Merge `patch` into the existing state record, when one exists. Used by the
|
|
271
|
+
* CLI to stamp `background`/`logFile` onto the record the Vite plugin wrote.
|
|
272
|
+
* Returns the merged record, or `undefined` when there was nothing to update.
|
|
273
|
+
*/
|
|
274
|
+
declare const updateDevServerState: (projectRoot: string, patch: Partial<DevServerState>) => DevServerState | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Remove `.lunora/dev.json`. Idempotent and never throws. When `expectedPid`
|
|
277
|
+
* is given, the file is only removed while it still records that PID — so a
|
|
278
|
+
* shutting-down server can't clobber the record a newer server just wrote.
|
|
279
|
+
*/
|
|
280
|
+
declare const clearDevServerState: (projectRoot: string, expectedPid?: number) => void;
|
|
281
|
+
/**
|
|
282
|
+
* The state record of a dev server that is verifiably running right now, or
|
|
283
|
+
* `undefined`. A record whose PID is dead — or recycled onto a different
|
|
284
|
+
* process (see {@link isRecordedProcessCurrent}) — is stale: it is cleared on
|
|
285
|
+
* the spot so subsequent starts don't keep re-reading a corpse.
|
|
286
|
+
*/
|
|
287
|
+
declare const readLiveDevServerState: (projectRoot: string) => DevServerState | undefined;
|
|
288
|
+
/** Result of {@link claimDevServerState}: claimed, or lost to the live server already recorded. */
|
|
289
|
+
interface ClaimDevServerStateResult {
|
|
290
|
+
/** The live record that won the race, when `ok` is `false`. */
|
|
291
|
+
existing?: DevServerState;
|
|
292
|
+
/** Whether this process now owns the record. */
|
|
293
|
+
ok: boolean;
|
|
294
|
+
}
|
|
295
|
+
declare const claimDevServerState: (projectRoot: string, state: DevServerState, options?: {
|
|
296
|
+
supersedePid?: number;
|
|
297
|
+
}) => ClaimDevServerStateResult;
|
|
168
298
|
/**
|
|
169
299
|
* The `.dev.vars` line grammar — one owner, shared by every reader/writer of the
|
|
170
300
|
* file so the format can't drift between packages. `@lunora/cli`'s `env`
|
|
@@ -1319,4 +1449,4 @@ interface WranglerProjectValidationResult {
|
|
|
1319
1449
|
* `{ problems, wranglerPath }` shape plus the structured `report`.
|
|
1320
1450
|
*/
|
|
1321
1451
|
declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
|
|
1322
|
-
export { ACCENT, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, 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 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 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, classifyEdit, createConfirm, detectAgentRules, detectFramework, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readLinkedProject, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, secretsForPackages, streamContainerLogs, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeLinkedProject };
|
|
1452
|
+
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 DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, 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 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, createConfirm, detectAgentRules, detectAiAgent, detectFramework, 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, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
export { AGENT_MODE_ENV, detectAiAgent } from './packem_shared/AGENT_MODE_ENV-DM1Siczo.mjs';
|
|
1
2
|
export { AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, LUNORA_SKILL_NAMES, ROOT_SKILL_NAME, claimAgentRulesHint, detectAgentRules } from './packem_shared/AGENT_RULES_DIR-lcgC08aE.mjs';
|
|
2
3
|
export { discoverContainerInfo } from './packem_shared/discoverContainerInfo-BXFs6Wav.mjs';
|
|
3
4
|
export { streamContainerLogs } from './packem_shared/streamContainerLogs-BZ4cOZwH.mjs';
|
|
4
|
-
export { detectFramework } from './packem_shared/detectFramework-
|
|
5
|
+
export { detectFramework, readProjectDependencyNames } from './packem_shared/detectFramework-U08038Yp.mjs';
|
|
6
|
+
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';
|
|
5
7
|
export { DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, parseDevVariableEntries } from './packem_shared/DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs';
|
|
6
8
|
export { inferLunoraBindings, packageNamesFromBindings } from './packem_shared/inferLunoraBindings-ByMwG-gH.mjs';
|
|
7
9
|
export { LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, readLinkedProject, writeLinkedProject } from './packem_shared/LINKED_PROJECT_DIR-CXwXzV_C.mjs';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { detectAiSession } from '@visulima/find-ai-runner';
|
|
2
|
+
|
|
3
|
+
const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
|
|
4
|
+
const isDisabled = (value) => {
|
|
5
|
+
const normalized = value.trim().toLowerCase();
|
|
6
|
+
return normalized === "0" || normalized === "false";
|
|
7
|
+
};
|
|
8
|
+
const detectAiAgent = (env = process.env) => {
|
|
9
|
+
const override = env[AGENT_MODE_ENV];
|
|
10
|
+
if (override !== void 0 && override !== "") {
|
|
11
|
+
return isDisabled(override) ? void 0 : { name: "agent (forced)", variable: AGENT_MODE_ENV };
|
|
12
|
+
}
|
|
13
|
+
const session = detectAiSession(env);
|
|
14
|
+
return session === void 0 ? void 0 : { name: session.agent, variable: session.variable };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { AGENT_MODE_ENV, detectAiAgent };
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync, rmSync, existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const DEV_STATE_DIR = ".lunora";
|
|
5
|
+
const DEV_STATE_FILE = join(DEV_STATE_DIR, "dev.json");
|
|
6
|
+
const DEV_LOG_FILE = join(DEV_STATE_DIR, "dev.log");
|
|
7
|
+
const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
|
|
8
|
+
const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
|
|
9
|
+
const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
|
|
10
|
+
const isObject = (value) => value !== null && typeof value === "object";
|
|
11
|
+
const stringField = (record, key) => {
|
|
12
|
+
const value = record[key];
|
|
13
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14
|
+
};
|
|
15
|
+
const isProcessAlive = (pid) => {
|
|
16
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
process.kill(pid, 0);
|
|
21
|
+
return true;
|
|
22
|
+
} catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const START_TIME_SKEW_MS = 1e4;
|
|
27
|
+
const LINUX_CLOCK_TICKS_PER_SECOND = 100;
|
|
28
|
+
const processStartTimeMs = (pid) => {
|
|
29
|
+
if (process.platform !== "linux") {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const stat = readFileSync(`/proc/${String(pid)}/stat`, "utf8");
|
|
34
|
+
const fields = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
|
|
35
|
+
const startTicks = Number(fields[19]);
|
|
36
|
+
const bootLine = readFileSync("/proc/stat", "utf8").split("\n").find((line) => line.startsWith("btime "));
|
|
37
|
+
const bootSeconds = Number(bootLine?.slice("btime ".length));
|
|
38
|
+
if (!Number.isFinite(startTicks) || !Number.isFinite(bootSeconds)) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
return bootSeconds * 1e3 + startTicks / LINUX_CLOCK_TICKS_PER_SECOND * 1e3;
|
|
42
|
+
} catch {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const isRecordedProcessCurrent = (state) => {
|
|
47
|
+
if (!isProcessAlive(state.pid)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const recordedAtMs = state.startedAt === void 0 ? Number.NaN : Date.parse(state.startedAt);
|
|
51
|
+
if (Number.isNaN(recordedAtMs)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
const actualStartMs = processStartTimeMs(state.pid);
|
|
55
|
+
return actualStartMs === void 0 || actualStartMs <= recordedAtMs + START_TIME_SKEW_MS;
|
|
56
|
+
};
|
|
57
|
+
const readDevServerState = (projectRoot) => {
|
|
58
|
+
const path = join(projectRoot, DEV_STATE_FILE);
|
|
59
|
+
if (!existsSync(path)) {
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
65
|
+
} catch {
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
if (!isObject(parsed) || typeof parsed["pid"] !== "number") {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
const url = stringField(parsed, "url");
|
|
72
|
+
if (url === void 0) {
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
background: parsed["background"] === true,
|
|
77
|
+
logFile: stringField(parsed, "logFile"),
|
|
78
|
+
mode: parsed["mode"] === "vite" ? "vite" : "cli",
|
|
79
|
+
pid: parsed["pid"],
|
|
80
|
+
startedAt: stringField(parsed, "startedAt"),
|
|
81
|
+
studioUrl: stringField(parsed, "studioUrl"),
|
|
82
|
+
url
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
const writeDevServerState = (projectRoot, state) => {
|
|
86
|
+
try {
|
|
87
|
+
mkdirSync(join(projectRoot, DEV_STATE_DIR), { recursive: true });
|
|
88
|
+
const path = join(projectRoot, DEV_STATE_FILE);
|
|
89
|
+
writeFileSync(path, `${JSON.stringify(state, void 0, 2)}
|
|
90
|
+
`, "utf8");
|
|
91
|
+
return path;
|
|
92
|
+
} catch {
|
|
93
|
+
return void 0;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const updateDevServerState = (projectRoot, patch) => {
|
|
97
|
+
const existing = readDevServerState(projectRoot);
|
|
98
|
+
if (existing === void 0) {
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
const merged = { ...existing, ...patch };
|
|
102
|
+
writeDevServerState(projectRoot, merged);
|
|
103
|
+
return merged;
|
|
104
|
+
};
|
|
105
|
+
const clearDevServerState = (projectRoot, expectedPid) => {
|
|
106
|
+
try {
|
|
107
|
+
if (expectedPid !== void 0) {
|
|
108
|
+
const current = readDevServerState(projectRoot);
|
|
109
|
+
if (current !== void 0 && current.pid !== expectedPid) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
rmSync(join(projectRoot, DEV_STATE_FILE), { force: true });
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const readLiveDevServerState = (projectRoot) => {
|
|
118
|
+
const state = readDevServerState(projectRoot);
|
|
119
|
+
if (state === void 0) {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
if (isRecordedProcessCurrent(state)) {
|
|
123
|
+
return state;
|
|
124
|
+
}
|
|
125
|
+
clearDevServerState(projectRoot, state.pid);
|
|
126
|
+
return void 0;
|
|
127
|
+
};
|
|
128
|
+
const resolveClaimConflict = (projectRoot, state, supersedePid) => {
|
|
129
|
+
const existing = readLiveDevServerState(projectRoot);
|
|
130
|
+
if (existing === void 0) {
|
|
131
|
+
return void 0;
|
|
132
|
+
}
|
|
133
|
+
if (supersedePid !== void 0 && existing.pid === supersedePid) {
|
|
134
|
+
return { ok: writeDevServerState(projectRoot, state) !== void 0 };
|
|
135
|
+
}
|
|
136
|
+
if (existing.pid !== state.pid) {
|
|
137
|
+
return { existing, ok: false };
|
|
138
|
+
}
|
|
139
|
+
return { ok: writeDevServerState(projectRoot, state) !== void 0 };
|
|
140
|
+
};
|
|
141
|
+
const claimDevServerState = (projectRoot, state, options) => {
|
|
142
|
+
const path = join(projectRoot, DEV_STATE_FILE);
|
|
143
|
+
const payload = `${JSON.stringify(state, void 0, 2)}
|
|
144
|
+
`;
|
|
145
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
146
|
+
try {
|
|
147
|
+
mkdirSync(join(projectRoot, DEV_STATE_DIR), { recursive: true });
|
|
148
|
+
writeFileSync(path, payload, { encoding: "utf8", flag: "wx" });
|
|
149
|
+
return { ok: true };
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (error.code !== "EEXIST") {
|
|
152
|
+
return { ok: writeDevServerState(projectRoot, state) !== void 0 };
|
|
153
|
+
}
|
|
154
|
+
const resolved = resolveClaimConflict(projectRoot, state, options?.supersedePid);
|
|
155
|
+
if (resolved !== void 0) {
|
|
156
|
+
return resolved;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { ok: writeDevServerState(projectRoot, state) !== void 0 };
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
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 };
|
|
@@ -12,7 +12,7 @@ const FRAMEWORK_SIGNATURES = [
|
|
|
12
12
|
{ class: "B", dependency: "astro", framework: "astro" }
|
|
13
13
|
];
|
|
14
14
|
const STANDALONE = { class: "C", framework: "none" };
|
|
15
|
-
const
|
|
15
|
+
const readProjectDependencyNames = (root) => {
|
|
16
16
|
const packageJsonPath = join(root, "package.json");
|
|
17
17
|
if (!existsSync(packageJsonPath)) {
|
|
18
18
|
return /* @__PURE__ */ new Set();
|
|
@@ -26,7 +26,7 @@ const readDependencyNames = (root) => {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const detectFramework = (root) => {
|
|
29
|
-
const dependencies =
|
|
29
|
+
const dependencies = readProjectDependencyNames(root);
|
|
30
30
|
if (dependencies.size === 0) {
|
|
31
31
|
return STANDALONE;
|
|
32
32
|
}
|
|
@@ -38,4 +38,4 @@ const detectFramework = (root) => {
|
|
|
38
38
|
return STANDALONE;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export { detectFramework };
|
|
41
|
+
export { detectFramework, readProjectDependencyNames };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/config",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.47",
|
|
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",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"@lunora/errors": "1.0.0-alpha.1",
|
|
56
56
|
"@lunora/seed": "1.0.0-alpha.14",
|
|
57
57
|
"@visulima/colorize": "2.0.0-alpha.14",
|
|
58
|
+
"@visulima/find-ai-runner": "1.0.0-alpha.9",
|
|
58
59
|
"dockerode": "^5.0.1",
|
|
59
60
|
"es-module-lexer": "^2.1.0",
|
|
60
61
|
"jsonc-parser": "^3.3.1",
|