@devicelink/dlink 0.2.2 → 0.3.1
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/README.md +24 -37
- package/index.js +343 -161
- package/index.js.map +4 -4
- package/package.json +1 -1
package/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../agent/src/cli/core/engine.ts", "../../agent/src/cli/core/types.ts", "../../agent/src/cli/core/result.ts", "../../agent/src/cli/core/job.ts", "../../agent/src/cli/core/events.ts", "../../agent/src/cli/core/storage.ts", "../../agent/src/cli/core/orchestrator.ts", "../../agent/src/cli/core/configuration.ts", "../../agent/src/cli/utils/config.builder.ts", "../../agent/src/cli/utils/machine-id.ts", "../../agent/src/cli/utils/key.builder.ts", "../../agent/src/cli/utils/get-directory-tag.ts", "../../agent/src/cli/core/eventBus.ts", "../../agent/src/storage/index.ts", "../../agent/src/cli/jobs/loadConfig.ts", "../../agent/src/cli/jobs/consoleCommand.ts", "../../agent/src/cli/jobs/contactServer.ts", "../../agent/src/cli/jobs/sendServerResult.ts", "../../agent/src/cli/jobs/refreshTokens.ts", "../../agent/src/cli/api/api.call.ts", "../../agent/src/cli/api/definitions/device-auth-start.api.ts", "../../agent/src/cli/api/definitions/device-auth-prove.api.ts", "../../agent/src/cli/api/definitions/device-auth-stream.api.ts", "../../agent/src/cli/api/definitions/device-auth-token.api.ts", "../../agent/src/cli/api/definitions/device-auth-refresh.api.ts", "../../agent/src/cli/api/index.ts", "../../
|
|
4
|
-
"sourcesContent": ["import crypto from \"node:crypto\";\nimport { DispatchResult, Deferred } from \"./result\";\nimport { EngineBus, Subscription } from \"./eventBus\";\nimport { Logger } from \"./logger\";\nimport { JobContext, JobCall, JobType } from \"./job\";\nimport { EnginePhase, JobState, LaneConfig, NotifyScope, RuntimeFlags } from \"./types\";\nimport { EngineEventMap, JobEvent } from \"./events\";\nimport { EngineStateFile, PersistedJob, Storage } from \"./storage\";\nimport { Orchestrator, OrchestratorContext } from \"./orchestrator\";\nimport { ArgvContext } from \"./context\";\nimport { Notifier } from \"./notifier\";\nimport { Configuration, ConfigurationContext } from \"./configuration\";\nimport { ConfigLoader } from \"../utils/config.builder\";\nimport { BaseStorage } from \"agent/src/storage\";\n\nexport class DispatchOptions {\n public readonly dedupeKey: string | null;\n public readonly parentId: string | null;\n public readonly overridePriority: number | null;\n public readonly overrideLane: string | null;\n\n public constructor(\n dedupeKey: string | null,\n parentId: string | null,\n overridePriority: number | null,\n overrideLane: string | null\n ) {\n this.dedupeKey = dedupeKey;\n this.parentId = parentId;\n this.overridePriority = overridePriority;\n this.overrideLane = overrideLane;\n }\n}\n\n\nexport class EngineRuntime {\n public phase: EnginePhase;\n public readonly flags: RuntimeFlags;\n\n public constructor(flags?: RuntimeFlags) {\n this.phase = EnginePhase.Idle;\n this.flags = flags ?? new RuntimeFlags(false);\n }\n}\n\nexport class Engine {\n public readonly argv: ArgvContext;\n public readonly configurationContext: ConfigurationContext;\n \n private readonly bus: EngineBus;\n private readonly notifier: Notifier;\n private readonly logger: Logger;\n private readonly storage: Storage;\n public readonly secrets: BaseStorage;\n\n public readonly runtime: EngineRuntime;\n\n private readonly lanes: Map<string, LaneConfig>;\n private readonly laneActive: Map<string, number>;\n\n private readonly registry: Map<string, JobType<unknown, unknown>>;\n\n private readonly orchestrators: Orchestrator[];\n private readonly orchestratorSubscriptions: Map<string, Subscription[]> = new Map();\n private readonly orchestratorAbort: AbortController;\n\n private readonly jobs: Map<string, PersistedJob>;\n private readonly queue: Array<string>;\n\n private readonly locksHeldBy: Map<string, string>;\n\n private readonly completions: Map<string, Deferred<DispatchResult<unknown>>>;\n private readonly dedupeIndex: Map<string, string>;\n\n private readonly engineAbort: AbortController;\n private readonly jobAbort: Map<string, AbortController>;\n\n private stopping: boolean;\n private running: boolean;\n\n private wakeFn: (() => void) | null;\n private wakePromise: Promise<void>;\n\n public constructor(params: {\n argv: ArgvContext;\n bus: EngineBus;\n secrets: BaseStorage;\n notifier: Notifier;\n logger: Logger;\n storage: Storage;\n lanes: readonly LaneConfig[];\n flags?: RuntimeFlags;\n }) {\n this.argv = params.argv;\n this.bus = params.bus;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.storage = params.storage;\n this.secrets = params.secrets;\n\n this.runtime = new EngineRuntime(params.flags);\n\n this.lanes = new Map();\n for (const lane of params.lanes) {\n this.lanes.set(lane.name, lane);\n }\n\n this.laneActive = new Map();\n for (const lane of params.lanes) {\n this.laneActive.set(lane.name, 0);\n }\n\n this.registry = new Map();\n\n this.orchestrators = [];\n this.orchestratorAbort = new AbortController();\n\n this.jobs = new Map();\n this.queue = [];\n\n this.locksHeldBy = new Map();\n\n this.completions = new Map();\n this.dedupeIndex = new Map();\n\n this.engineAbort = new AbortController();\n this.jobAbort = new Map();\n\n this.stopping = false;\n this.running = false;\n\n this.wakeFn = null;\n this.wakePromise = this.resetWake();\n\n const config = new Configuration();\n const configLoader = new ConfigLoader(this.notifier);\n this.configurationContext = new ConfigurationContext(config, configLoader);\n }\n\n public applyConfiguration(configuration: Configuration): void {\n this.configurationContext.apply(configuration);\n }\n\n public setPhase(phase: EnginePhase): void {\n this.runtime.phase = phase;\n }\n\n public getBus(): EngineBus {\n return this.bus;\n }\n\n public register(jobType: JobType<unknown, unknown>): void {\n const name = jobType.options.name;\n if (this.registry.has(name)) {\n throw new Error(`JobType already registered: ${name}`);\n }\n this.registry.set(name, jobType);\n }\n\n public registerOrchestrator(orch: Orchestrator): void {\n const exists = this.orchestrators.some((o) => o.name === orch.name);\n if (exists) {\n throw new Error(`Orchestrator already registered: ${orch.name}`);\n }\n\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n orch.onRegister?.(ctx);\n this.setupOrchestratorSubscriptions(orch, ctx);\n this.orchestrators.push(orch);\n }\n\n private setupOrchestratorSubscriptions(orch: Orchestrator, ctx: OrchestratorContext): void {\n const map = orch.handlers?.();\n if (map) {\n const subs: Subscription[] = [];\n (Object.keys(map) as Array<keyof EngineEventMap>).forEach((eventName) => {\n const fn = map[eventName];\n if (!fn) return;\n \n subs.push(\n this.bus.on(eventName, (payload: EngineEventMap[keyof EngineEventMap]) => {\n // don't let exceptions crash emit()\n Promise.resolve(fn(payload as never, ctx)).catch((err) => {\n this.notifier.error(\n `handler error (${orch.name}/${String(eventName)}): ${String(err)}`,\n { scope: NotifyScope.System }\n );\n });\n })\n );\n });\n this.orchestratorSubscriptions.set(orch.name, subs);\n }\n }\n\n public async init(): Promise<void> {\n const state = await this.storage.load();\n for (const [id, job] of Object.entries(state.jobs)) {\n this.jobs.set(id, new PersistedJob(job));\n }\n\n // Crash recovery: running -> queued\n for (const job of this.jobs.values()) {\n if (job.state === JobState.Running) {\n job.state = JobState.Queued;\n job.nextRunAt = Date.now();\n job.updatedAt = Date.now();\n }\n if (job.dedupeKey) this.dedupeIndex.set(job.dedupeKey, job.id);\n if (job.state === JobState.Queued) this.queue.push(job.id);\n }\n }\n\n\n public async start(): Promise<void> {\n if (this.running) return;\n\n this.running = true;\n this.runtime.phase = EnginePhase.Running;\n\n // Make process-level crashes go through stop, not kill loop silently\n process.on(\"uncaughtException\", (err) => {\n this.notifier.error(`uncaughtException: ${err.stack ? err.stack : String(err)}`, { scope: NotifyScope.System });\n this.requestStop(\"uncaughtException\");\n });\n process.on(\"unhandledRejection\", (reason) => {\n this.notifier.error(`unhandledRejection: ${String(reason)}`, { scope: NotifyScope.System });\n // policy: keep running; user can stop\n });\n\n this.bus.emit(\"engine:started\", Date.now());\n\n\n try {\n // Start orchestrators, but don't let long-running tasks block scheduler.\n await this.startOrchestratorsSafe();\n \n // Run scheduler until stopping\n await this.loopGuarded();\n } finally {\n // Ensure orchestrators are stopped exactly once\n await this.stopOrchestratorsSafe();\n await this.persist();\n this.bus.emit(\"engine:stopped\", Date.now());\n }\n }\n\n public requestStop(reason: string): void {\n if (this.stopping) return;\n this.stopping = true;\n this.runtime.phase = EnginePhase.Stopping;\n this.bus.emit(\"engine:stopping\", reason);\n \n this.engineAbort.abort(new Error(`Stopping: ${reason}`));\n this.orchestratorAbort.abort(new Error(`Stopping: ${reason}`));\n \n // cancel running jobs (your logic is fine)\n for (const [jobId, ctrl] of this.jobAbort.entries()) {\n const job = this.jobs.get(jobId);\n if (job?.cancellable) ctrl.abort(new Error(\"Cancelled by user\"));\n }\n \n this.wake();\n }\n\n\n public async dispatch<TIn, TOut>(\n job: JobCall<TIn, TOut>,\n options?: DispatchOptions\n ): Promise<DispatchResult<TOut>> {\n const opts = options ? options : new DispatchOptions(null, null, null, null);\n\n const jobTypeName = job.type.options.name;\n\n // Ensure job type is registered\n if (!this.registry.has(jobTypeName)) {\n const err = new Error(`JobType not registered: ${jobTypeName}`);\n return DispatchResult.failure<TOut>(err);\n }\n\n // dedupe behavior if key provided\n if (opts.dedupeKey) {\n const existingId = this.dedupeIndex.get(opts.dedupeKey);\n if (existingId) {\n const existing = this.jobs.get(existingId);\n if (existing && (existing.state === JobState.Queued || existing.state === JobState.Running)) {\n const existingCompletion = this.completions.get(existingId);\n if (existingCompletion) {\n const r = await existingCompletion.promise;\n return r as DispatchResult<TOut>;\n }\n }\n }\n }\n\n const jobId = this.newId();\n\n const completion = new Deferred<DispatchResult<unknown>>();\n this.completions.set(jobId, completion);\n\n const lane = opts.overrideLane ? opts.overrideLane : job.type.options.lane;\n const priority = opts.overridePriority !== null ? opts.overridePriority : job.type.options.priority;\n\n const persisted = new PersistedJob({\n id: jobId,\n jobType: jobTypeName,\n inputJson: job.input === undefined ? \"null\" : JSON.stringify(job.input),\n\n state: JobState.Queued,\n lane,\n priority,\n locks: job.type.options.locks,\n\n attempts: 0,\n maxAttempts: job.type.options.maxAttempts,\n nextRunAt: Date.now(),\n\n cancellable: job.type.options.cancellable,\n\n parentId: opts.parentId,\n dedupeKey: opts.dedupeKey,\n\n lastError: null,\n\n createdAt: Date.now(),\n updatedAt: Date.now(),\n });\n\n this.jobs.set(jobId, persisted);\n this.queue.push(jobId);\n\n if (opts.dedupeKey) this.dedupeIndex.set(opts.dedupeKey, jobId);\n\n this.emitJobEvent(persisted, JobState.Queued, null, null);\n await this.persist();\n\n this.wake();\n\n const result = await completion.promise;\n return result as DispatchResult<TOut>;\n }\n\n /* ------------------------\n Scheduler loop safety\n ------------------------- */\n\n private async loopGuarded(): Promise<void> {\n while (!this.stopping) {\n try {\n await this.loopOnce();\n } catch (err) {\n this.notifier.error(`Engine loop error: ${String(err)}`, { scope: NotifyScope.System });\n // prevent spin on repeated bug\n await new Promise<void>((resolve) => setTimeout(resolve, 250));\n }\n }\n }\n\n private async loopOnce(): Promise<void> {\n let dispatchedCount = 0;\n\n while (true) {\n const jobId = this.pickNextRunnable();\n if (!jobId) break;\n dispatchedCount += 1;\n\n // IMPORTANT: never await job execution in the loop\n void this.runJobSafe(jobId);\n }\n\n if (dispatchedCount === 0) {\n await this.wakePromise;\n this.wakePromise = this.resetWake();\n }\n }\n\n private async runJobSafe(jobId: string): Promise<void> {\n try {\n await this.runJobInternal(jobId);\n } catch (err) {\n // This should never happen; keep engine alive anyway.\n this.notifier.error(`runJobInternal crashed: ${String(err)}`, { scope: NotifyScope.System });\n\n const completion = this.completions.get(jobId);\n if (completion) completion.resolve(DispatchResult.failure(new Error(String(err))));\n } finally {\n this.wake();\n }\n }\n\n private pickNextRunnable(): string | null {\n const t = Date.now();\n\n let bestId: string | null = null;\n let bestPriority = Number.NEGATIVE_INFINITY;\n let bestNextRun = Number.POSITIVE_INFINITY;\n\n for (const id of this.queue) {\n const job = this.jobs.get(id);\n if (!job) continue;\n if (job.state !== JobState.Queued) continue;\n\n // Stop policy: only \"console\" lane jobs can run while stopping\n if (this.stopping && job.lane !== \"console\") continue;\n\n if (job.nextRunAt > t) continue;\n if (!this.canRunInLane(job.lane)) continue;\n if (!this.canAcquireLocks(job)) continue;\n\n if (job.priority > bestPriority || (job.priority === bestPriority && job.nextRunAt < bestNextRun)) {\n bestPriority = job.priority;\n bestNextRun = job.nextRunAt;\n bestId = id;\n }\n }\n\n if (!bestId) return null;\n\n const idx = this.queue.indexOf(bestId);\n if (idx >= 0) this.queue.splice(idx, 1);\n\n return bestId;\n }\n\n private canRunInLane(laneName: string): boolean {\n const lane = this.lanes.get(laneName);\n if (!lane) return false;\n const active = this.laneActive.get(laneName);\n if (active === undefined) return false;\n return active < lane.concurrency;\n }\n\n private canAcquireLocks(job: PersistedJob): boolean {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (!holder) continue;\n if (holder === job.id) continue;\n if (job.parentId && holder === job.parentId) continue; // child allowed under parent lock\n return false;\n }\n return true;\n }\n\n private acquireLocks(job: PersistedJob): void {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (!holder) this.locksHeldBy.set(lock, job.id);\n }\n }\n\n private releaseLocks(job: PersistedJob): void {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (holder === job.id) this.locksHeldBy.delete(lock);\n }\n }\n\n /* ------------------------\n Job execution\n ------------------------- */\n\n private async runJobInternal(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) return;\n\n const jobType = this.registry.get(job.jobType);\n if (!jobType) {\n this.completeFailure(jobId, new Error(`No registered JobType: ${job.jobType}`));\n return;\n }\n\n const laneActive = this.laneActive.get(job.lane);\n if (laneActive === undefined) {\n this.completeFailure(jobId, new Error(`Unknown lane: ${job.lane}`));\n return;\n }\n\n const ctrl = new AbortController();\n this.jobAbort.set(jobId, ctrl);\n\n if (job.cancellable) {\n const engineSignal = this.engineAbort.signal;\n if (engineSignal.aborted) ctrl.abort(engineSignal.reason instanceof Error ? engineSignal.reason : new Error(\"Stopped\"));\n else {\n engineSignal.addEventListener(\n \"abort\",\n () => ctrl.abort(engineSignal.reason instanceof Error ? engineSignal.reason : new Error(\"Stopped\")),\n { once: true }\n );\n }\n }\n\n this.laneActive.set(job.lane, laneActive + 1);\n this.acquireLocks(job);\n\n job.state = JobState.Running;\n job.updatedAt = Date.now();\n await this.persist();\n this.emitJobEvent(job, JobState.Running, null, null);\n\n const ctx = new JobContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: ctrl.signal,\n dispatch: async <TIn, TOut>(call: JobCall<TIn, TOut>, opts: DispatchOptions) => this.dispatch(call, opts),\n });\n\n try {\n const parsed = JSON.parse(job.inputJson) as unknown;\n const input = parsed === null ? undefined : parsed;\n const output = await (jobType as JobType<unknown, unknown>).run(input, ctx);\n\n job.state = JobState.Succeeded;\n job.updatedAt = Date.now();\n job.lastError = null;\n\n await this.persist();\n this.emitJobEvent(job, JobState.Succeeded, null, null);\n\n this.completeSuccess(jobId, output);\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Unknown error\");\n\n job.attempts += 1;\n job.updatedAt = Date.now();\n job.lastError = err.message;\n\n const aborted = ctrl.signal.aborted;\n if (aborted) {\n job.state = JobState.Failed;\n await this.persist();\n this.emitJobEvent(job, JobState.Failed, err.message, null);\n this.notifier.error(`Job ${job.jobType} (${jobId.substring(0, 8)}) cancelled: ${err.message}`);\n this.completeCancelled(jobId, err);\n } else {\n const canRetry = job.attempts < job.maxAttempts && !this.stopping;\n if (canRetry) {\n const delay = backoffMs(job.attempts);\n job.state = JobState.Queued;\n job.nextRunAt = Date.now() + delay;\n await this.persist();\n\n this.queue.push(job.id);\n this.emitJobEvent(job, JobState.Queued, err.message, job.nextRunAt);\n this.notifier.warn(`Job ${job.jobType} (${jobId.substring(0, 8)}) failed, retrying in ${delay}ms (attempt ${job.attempts}/${job.maxAttempts}): ${err.message}`);\n } else {\n job.state = JobState.Failed;\n await this.persist();\n this.emitJobEvent(job, JobState.Failed, err.message, null);\n this.notifier.error(`Job ${job.jobType} (${jobId.substring(0, 8)}) failed after ${job.attempts} attempt(s): ${err.message}`);\n this.completeFailure(jobId, err);\n }\n }\n } finally {\n this.releaseLocks(job);\n\n const currentActive = this.laneActive.get(job.lane);\n if (currentActive !== undefined) this.laneActive.set(job.lane, Math.max(0, currentActive - 1));\n\n this.jobAbort.delete(jobId);\n this.wake();\n }\n }\n\n /* ------------------------\n Orchestrators\n ------------------------- */\n\n private async startOrchestratorsSafe(): Promise<void> {\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n for (const orch of this.orchestrators) {\n Promise.resolve()\n .then(() => orch.onStart?.(ctx))\n .then(() => orch.onStarted?.(ctx))\n .catch((err) => this.notifier.error(`Orchestrator start failed (${orch.name}): ${String(err)}`, { scope: NotifyScope.System }));\n }\n }\n\n private async stopOrchestratorsSafe(): Promise<void> {\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n for (let i = this.orchestrators.length - 1; i >= 0; i--) {\n const orch = this.orchestrators[i];\n try {\n await orch.onStop?.(ctx);\n orch.onStopped?.(ctx);\n } catch (err) {\n this.notifier.error(`Orchestrator stop failed (${orch.name}): ${String(err)}`, { scope: NotifyScope.System });\n }\n\n const subs = this.orchestratorSubscriptions.get(orch.name);\n if (subs) {\n for (const s of subs) s.unsubscribe();\n this.orchestratorSubscriptions.delete(orch.name);\n }\n }\n }\n\n /* ------------------------\n Completion + events + persistence\n ------------------------- */\n\n private emitJobEvent(job: PersistedJob, state: JobState, error: string | null, nextRunAt: number | null): void {\n this.bus.emit(\n \"job:event\",\n new JobEvent({\n ts: Date.now(),\n jobId: job.id,\n jobType: job.jobType,\n state,\n attempt: job.attempts,\n maxAttempts: job.maxAttempts,\n lane: job.lane,\n priority: job.priority,\n error,\n nextRunAt,\n })\n );\n }\n\n private completeSuccess(jobId: string, output: unknown): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.success(output));\n }\n\n private completeFailure(jobId: string, err: Error): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.failure(err));\n }\n\n private completeCancelled(jobId: string, err: Error): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.cancelled(err));\n }\n\n private async persist(): Promise<void> {\n const jobs: Record<string, PersistedJob> = {};\n for (const [id, job] of this.jobs.entries()) jobs[id] = job;\n await this.storage.save(new EngineStateFile(jobs));\n }\n\n private wake(): void {\n if (this.wakeFn) this.wakeFn();\n }\n\n private resetWake(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.wakeFn = resolve;\n });\n }\n\n private newId(): string {\n return crypto.randomBytes(8).toString(\"hex\");\n }\n}\n\nfunction backoffMs(attempt: number): number {\n const base = 300;\n const max = 30_000;\n const exp = Math.min(max, base * 2 ** (attempt - 1));\n const jitter = Math.floor(Math.random() * 200);\n return exp + jitter;\n}\n", "export enum DispatchStatus {\n Success = \"success\",\n Failure = \"failure\",\n Cancelled = \"cancelled\",\n }\n \n export enum JobState {\n Queued = \"queued\",\n Running = \"running\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n }\n \n export enum LogLevel {\n Info = \"info\",\n Warn = \"warn\",\n Error = \"error\",\n Debug = \"debug\",\n Success = \"success\",\n }\n \n export enum NotifyScope {\n Default = \"default\",\n System = \"system\",\n }\n \n export enum NotifyKind {\n Status = \"status\",\n Info = \"info\",\n Success = \"success\",\n Warning = \"warning\",\n Error = \"error\",\n }\n \n export class RuntimeFlags {\n public debug: boolean;\n \n public constructor(debug: boolean) {\n this.debug = debug;\n }\n }\n \nexport enum EnginePhase {\n Idle = \"idle\",\n Booting = \"booting\",\n Running = \"running\",\n Stopping = \"stopping\",\n}\n \n export class LaneConfig {\n public readonly name: string;\n public readonly concurrency: number;\n \n public constructor(name: string, concurrency: number) {\n this.name = name;\n this.concurrency = concurrency;\n }\n }\n ", "import { DispatchStatus } from \"./types\";\r\n\r\nexport class DispatchResult<TOutput> {\r\n public readonly status: DispatchStatus;\r\n public readonly output: TOutput | null;\r\n public readonly error: Error | null;\r\n\r\n private constructor(status: DispatchStatus, output: TOutput | null, error: Error | null) {\r\n this.status = status;\r\n this.output = output;\r\n this.error = error;\r\n }\r\n\r\n public static success<TOutput>(output: TOutput): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Success, output, null);\r\n }\r\n\r\n public static failure<TOutput>(error: Error): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Failure, null, error);\r\n }\r\n\r\n public static cancelled<TOutput>(error: Error): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Cancelled, null, error);\r\n }\r\n}\r\n\r\nexport class Deferred<T> {\r\n public readonly promise: Promise<T>;\r\n private resolveFn: (value: T) => void;\r\n private rejectFn: (error: Error) => void;\r\n\r\n public constructor() {\r\n this.resolveFn = () => {};\r\n this.rejectFn = () => {};\r\n this.promise = new Promise<T>((resolve, reject) => {\r\n this.resolveFn = resolve;\r\n this.rejectFn = reject;\r\n });\r\n }\r\n\r\n public resolve(value: T): void {\r\n this.resolveFn(value);\r\n }\r\n\r\n public reject(error: Error): void {\r\n this.rejectFn(error);\r\n }\r\n}\r\n", "import { DispatchResult } from \"./result\";\nimport { Logger } from \"./logger\";\nimport { NotifyScope, RuntimeFlags, NotifyKind } from \"./types\";\nimport { Engine, DispatchOptions } from \"./engine\";\nimport { Notifier } from \"./notifier\";\nimport { EngineBus } from \"./eventBus\";\n\nexport class JobTypeOptions {\n public readonly name: string;\n public readonly lane: string;\n public readonly priority: number;\n public readonly locks: readonly string[];\n public readonly maxAttempts: number;\n public readonly cancellable: boolean;\n\n public constructor(params: {\n name: string;\n lane: string;\n priority: number;\n locks: readonly string[];\n maxAttempts: number;\n cancellable: boolean;\n }) {\n this.name = params.name;\n this.lane = params.lane;\n this.priority = params.priority;\n this.locks = params.locks;\n this.maxAttempts = params.maxAttempts;\n this.cancellable = params.cancellable;\n }\n}\n\nexport abstract class JobType<TIn, TOut> {\n public readonly options: JobTypeOptions;\n\n protected constructor(options: JobTypeOptions) {\n this.options = options;\n }\n\n public abstract run(input: TIn, ctx: JobContext): Promise<TOut>;\n}\n\nexport class JobCall<TIn, TOut> {\n public readonly type: JobType<TIn, TOut>;\n public readonly input: TIn;\n\n public constructor(type: JobType<TIn, TOut>, input: TIn) {\n this.type = type;\n this.input = input;\n }\n}\n\nexport class JobContext {\n public readonly bus: EngineBus;\n public readonly logger: Logger;\n public readonly notifier: Notifier;\n public readonly flags: RuntimeFlags;\n public readonly signal: AbortSignal;\n public readonly engine: Engine;\n\n private readonly dispatchFn: <TIn, TOut>(job: JobCall<TIn, TOut>, options: DispatchOptions) => Promise<DispatchResult<TOut>>;\n\n public constructor(params: {\n bus: EngineBus;\n engine: Engine;\n logger: Logger;\n notifier: Notifier;\n flags: RuntimeFlags;\n signal: AbortSignal;\n dispatch: <TIn, TOut>(job: JobCall<TIn, TOut>, options: DispatchOptions) => Promise<DispatchResult<TOut>>;\n }) {\n this.bus = params.bus;\n this.engine = params.engine;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.flags = params.flags;\n this.signal = params.signal;\n this.dispatchFn = params.dispatch;\n }\n\n public dispatch<TIn, TOut>(job: JobCall<TIn, TOut>, options?: DispatchOptions): Promise<DispatchResult<TOut>> {\n const safeOptions = options ? options : new DispatchOptions(null, null, null, null);\n return this.dispatchFn(job, safeOptions);\n }\n}\n", "import { JobState, LogLevel, NotifyScope, NotifyKind } from './types';\nimport { Configuration } from './configuration';\nimport type { ConnectAck, RefreshAccessTokenAck, SessionInitAck, SessionConflictRequest, ToolCallRequest } from '@devicelink-workspace/domain';\n\n\nexport type LogOptions = {\n ts?: number;\n category?: string[]\n};\n\nexport class LogEntry {\n public readonly ts: number;\n public readonly message: string;\n\n public constructor(\n message: string,\n options?: LogOptions,\n ) {\n this.ts = options?.ts ?? Date.now();\n this.message = message;\n }\n}\n\n export type NotifyOptions = {\n ts?: number;\n kind?: NotifyKind;\n scope?: NotifyScope;\n groupKey?: string;\n category?: string[]\n};\n\nexport class NotifyEvent {\n public readonly id: string;\n public readonly ts: number;\n public readonly groupKey?: string;\n public readonly kind: NotifyKind;\n public readonly scope: NotifyScope;\n public readonly message: string;\n public readonly category?: string[]\n\n public constructor(\n message: string,\n options?: NotifyOptions,\n ) {\n this.id = crypto.randomUUID();\n this.ts = options?.ts ?? Date.now();\n this.kind = options?.kind ?? NotifyKind.Info;\n this.scope = options?.scope ?? NotifyScope.Default;\n this.message = message;\n this.groupKey = options?.groupKey;\n this.category = options?.category ?? [];\n }\n}\n\nexport class JobEvent {\n public readonly ts: number;\n public readonly jobId: string;\n public readonly jobType: string;\n public readonly state: JobState;\n public readonly attempt: number;\n public readonly maxAttempts: number;\n public readonly lane: string;\n public readonly priority: number;\n public readonly error: string | null;\n public readonly nextRunAt: number | null;\n\n public constructor(params: {\n ts: number;\n jobId: string;\n jobType: string;\n state: JobState;\n attempt: number;\n maxAttempts: number;\n lane: string;\n priority: number;\n error: string | null;\n nextRunAt: number | null;\n }) {\n this.ts = params.ts;\n this.jobId = params.jobId;\n this.jobType = params.jobType;\n this.state = params.state;\n this.attempt = params.attempt;\n this.maxAttempts = params.maxAttempts;\n this.lane = params.lane;\n this.priority = params.priority;\n this.error = params.error;\n this.nextRunAt = params.nextRunAt;\n }\n}\n\n\n\n/** Shared payloads for WS events */\nexport type WsConnected = { url: string; attempt: number };\nexport type WsDisconnected = { code: number; reason?: string; wasClean?: boolean };\nexport type WsRetrying = { retryInSec: number; attempt: number };\nexport type WsRx = { text: string; bytes?: number };\nexport type WsTx = { text: string; bytes?: number; type?: string };\n\n/** Auth payloads */\nexport type TokensUpdated = {\n accessToken: string;\n refreshToken: string;\n expSec: number | undefined;\n};\n\nexport interface EngineEventMap {\n // core\n log: LogEntry;\n \"notify:event\": NotifyEvent;\n\n // engine lifecycle\n \"engine:started\": number;\n \"engine:stopping\": string;\n \"engine:stopped\": number;\n\n // runtime\n \"runtime:debug:changed\": { enabled: boolean };\n\n // console\n \"console:command\": string;\n\n // config (standard)\n \"config:loaded\": Configuration;\n \"config:cache:validated\": void;\n \"config:save:requested\": Configuration;\n \"config:saved\": void;\n\n // ws transport (standard)\n \"ws:connecting\": { url: string; attempt: number };\n \"ws:connected\": WsConnected;\n \"ws:disconnected\": WsDisconnected;\n \"ws:disconnect\": { reason?: string };\n \"ws:retrying\": WsRetrying;\n \"ws:rx\": WsRx;\n \"ws:tx\": WsTx;\n\n // auth protocol state machine (typed)\n \"auth:signin:requested\": void;\n \"auth:signin:completed\": void;\n \"auth:signout:requested\": void;\n \"auth:ws:reconnect\": void;\n \"auth:connect_ack\": ConnectAck;\n \"auth:refresh_ack\": RefreshAccessTokenAck;\n \"auth:session_init_ack\": SessionInitAck;\n \"auth:session_conflict\": SessionConflictRequest;\n \"auth:session_conflict:resolve\": { choice: 'USE_NEW' | 'KEEP_OLD' };\n \"auth:tokens:updated\": TokensUpdated;\n\n \"meta:data:requested:tools\": void;\n \"meta:data:requested:directories\": void;\n\n // tools\n \"tool:call\": ToolCallRequest;\n\n // ui\n \"ui:initialized\": number;\n\n // job\n \"job:event\": JobEvent;\n}", "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as crypto from \"node:crypto\";\n\nexport class EngineStateFile {\n public readonly jobs: Record<string, PersistedJob>;\n\n public constructor(jobs: Record<string, PersistedJob>) {\n this.jobs = jobs;\n }\n}\n\nexport class PersistedJob {\n public id: string;\n public jobType: string;\n public inputJson: string;\n\n public state: string;\n public lane: string;\n public priority: number;\n public locks: readonly string[];\n\n public attempts: number;\n public maxAttempts: number;\n\n public nextRunAt: number;\n\n public cancellable: boolean;\n\n public parentId: string | null;\n public dedupeKey: string | null;\n\n public lastError: string | null;\n\n public createdAt: number;\n public updatedAt: number;\n\n public constructor(params: PersistedJob) {\n this.id = params.id;\n this.jobType = params.jobType;\n this.inputJson = params.inputJson;\n\n this.state = params.state;\n this.lane = params.lane;\n this.priority = params.priority;\n this.locks = params.locks;\n\n this.attempts = params.attempts;\n this.maxAttempts = params.maxAttempts;\n\n this.nextRunAt = params.nextRunAt;\n\n this.cancellable = params.cancellable;\n\n this.parentId = params.parentId;\n this.dedupeKey = params.dedupeKey;\n\n this.lastError = params.lastError;\n\n this.createdAt = params.createdAt;\n this.updatedAt = params.updatedAt;\n }\n}\n\nexport interface Storage {\n load(): Promise<EngineStateFile>;\n save(state: EngineStateFile): Promise<void>;\n}\n\nexport class JsonFileStorage implements Storage {\n private readonly filePath: string;\n\n public constructor(dir: string, fileName: string) {\n this.filePath = path.join(dir, fileName);\n }\n\n public async load(): Promise<EngineStateFile> {\n try {\n const raw = await fs.readFile(this.filePath, \"utf8\");\n const parsed = JSON.parse(raw) as { jobs: Record<string, PersistedJob> };\n const jobs = parsed.jobs ? parsed.jobs : {};\n return new EngineStateFile(jobs);\n } catch {\n return new EngineStateFile({});\n }\n }\n\n public async save(state: EngineStateFile): Promise<void> {\n await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n const tmp = this.filePath + \".tmp\";\n const raw = JSON.stringify(state, null, 2);\n await fs.writeFile(tmp, raw, \"utf8\");\n await fs.rename(tmp, this.filePath);\n }\n}\n\nexport class MemoryStorage implements Storage {\n private state: EngineStateFile;\n\n public constructor(initial?: EngineStateFile) {\n this.state = initial ?? new EngineStateFile({});\n }\n\n public async load(): Promise<EngineStateFile> {\n // Return a deep copy so callers can't mutate internal reference accidentally\n return new EngineStateFile(structuredClone(this.state.jobs));\n }\n\n public async save(state: EngineStateFile): Promise<void> {\n // Store a deep copy\n this.state = new EngineStateFile(structuredClone(state.jobs));\n }\n}\n", "import { Engine } from \"./engine\";\nimport { EngineBus } from \"./eventBus\";\nimport { Logger } from \"./logger\";\nimport { RuntimeFlags } from \"./types\";\nimport { EngineEventMap } from \"./events\";\nimport { Subscription } from \"./eventBus\";\nimport { Notifier } from \"./notifier\";\n\nexport class OrchestratorContext {\n public readonly engine: Engine;\n public readonly bus: EngineBus;\n public readonly logger: Logger;\n public readonly notifier: Notifier;\n public readonly flags: RuntimeFlags;\n public readonly signal: AbortSignal;\n\n public constructor(params: {\n engine: Engine;\n bus: EngineBus;\n logger: Logger;\n notifier: Notifier;\n flags: RuntimeFlags;\n signal: AbortSignal;\n }) {\n this.engine = params.engine;\n this.bus = params.bus;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.flags = params.flags;\n this.signal = params.signal;\n }\n\n public on<K extends keyof EngineEventMap>(event: K, handler: (payload: EngineEventMap[K]) => void): Subscription {\n return this.bus.on(event, handler);\n }\n\n}\n\ntype HandlerMap<TEvents> = {\n [K in keyof TEvents]?: (payload: TEvents[K], ctx: OrchestratorContext) => void | Promise<void>;\n};\n\nexport interface Orchestrator {\n readonly name: string;\n \n\n onRegister?(ctx: OrchestratorContext): void;\n\n onStart?(ctx: OrchestratorContext): Promise<void>;\n\n onStarted?(ctx: OrchestratorContext): Promise<void>;\n\n onStop?(ctx: OrchestratorContext): Promise<void>;\n\n onStopped?(ctx: OrchestratorContext): Promise<void>;\n\n handlers?(): HandlerMap<EngineEventMap>;\n}\n", "import { ConfigLoader } from \"../utils/config.builder\";\n\nexport type Directory = {\n id: string;\n name: string;\n path: string;\n tag: string;\n}\n\nexport type Device = {\n id: string;\n name: string;\n tag: string;\n keys: {\n public: string;\n };\n}\n\nexport type Tokens = {\n accessTokenExpSec?: number;\n}\n\nexport class Configuration {\n version: number = 1;\n controlBaseUrl?: string;\n bridgeWsUrl?: string;\n directories: Directory[];\n device?: Device;\n tokens?: Tokens;\n\n public constructor() {\n this.directories = [];\n }\n}\n\nexport class ConfigurationContext {\n public _configuration: Configuration;\n public readonly loader: ConfigLoader;\n\n public get configuration(): Configuration {\n return this._configuration;\n }\n\n public constructor(configuration: Configuration, loader: ConfigLoader) {\n this._configuration = configuration;\n this.loader = loader;\n }\n\n public apply(configuration: Configuration): void {\n this._configuration = configuration;\n }\n}", "import path from 'node:path';\r\nimport os from 'node:os';\r\nimport fs from 'node:fs';\r\nimport { Configuration, Directory, Device, Tokens } from \"../core/configuration\";\r\nimport { ArgvContext } from \"../core/context\";\r\nimport dotenv from 'dotenv';\r\nimport get from 'lodash/get.js';\r\nimport isArray from 'lodash/isArray.js';\r\nimport isObject from 'lodash/isObject.js';\r\nimport isString from 'lodash/isString.js';\r\nimport isEmpty from 'lodash/isEmpty.js';\r\nimport defaultTo from 'lodash/defaultTo.js';\r\nimport { Notifier } from '../core/notifier';\r\nimport { NotifyScope } from '../core/types';\r\nimport { getMachineId } from './machine-id';\r\nimport { KeyBuilder } from './key.builder';\r\nimport { getDirectoryTag, pathToUuidLikeSha256 } from './get-directory-tag';\r\n\r\nconst DEFAULT_CONFIG: Configuration = {\r\n version: 1,\r\n controlBaseUrl: '',\r\n bridgeWsUrl: '',\r\n directories: [],\r\n device: undefined,\r\n};\r\n\r\ntype ProcessEnv = {\r\n [key: string]: string | undefined;\r\n}\r\n\r\nexport class ConfigLoader {\r\n private readonly _notifier: Notifier;\r\n private argv!: ArgvContext;\r\n\r\n private config: Configuration = DEFAULT_CONFIG;\r\n private envFile: dotenv.DotenvConfigOutput = dotenv.config({ quiet: true });\r\n private processEnv: ProcessEnv = {};\r\n private productionEnv: ProcessEnv = {};\r\n private configFileContent: Record<string, unknown> = {};\r\n private _privateKeyCache: string | undefined = undefined;\r\n private _privateKeyToStore: string | undefined = undefined;\r\n\r\n public constructor(notifier: Notifier) {\r\n this._notifier = notifier;\r\n this.loadProductionEnv();\r\n }\r\n\r\n /**\r\n * Load .env.production as the lowest-priority fallback.\r\n * Looks for the file relative to the package root so it works\r\n * both in development (agent/.env.production) and when installed\r\n * from npm (alongside index.js).\r\n */\r\n private loadProductionEnv(): void {\r\n const candidates = [\r\n // npm install: .env.production alongside index.js\r\n path.resolve(path.dirname(process.argv[1] ?? '.'), '.env.production'),\r\n // monorepo dev: agent/.env.production\r\n path.resolve(process.cwd(), '.env.production'),\r\n ];\r\n\r\n for (const candidate of candidates) {\r\n try {\r\n if (fs.existsSync(candidate)) {\r\n const result = dotenv.config({ path: candidate, quiet: true });\r\n if (result.parsed) {\r\n this.productionEnv = result.parsed;\r\n }\r\n return;\r\n }\r\n } catch {\r\n // Silently continue\r\n }\r\n }\r\n }\r\n\r\n public setPrivateKeyCache(value: string | undefined): void {\r\n this._privateKeyCache = value;\r\n }\r\n\r\n public getPrivateKeyToStore(): string | undefined {\r\n return this._privateKeyToStore;\r\n }\r\n\r\n public withDefaultConfig(): ConfigLoader {\r\n this.config.version = DEFAULT_CONFIG.version;\r\n this.config.controlBaseUrl = DEFAULT_CONFIG.controlBaseUrl;\r\n this.config.bridgeWsUrl = DEFAULT_CONFIG.bridgeWsUrl;\r\n this.config.directories = DEFAULT_CONFIG.directories;\r\n this.config.device = DEFAULT_CONFIG.device;\r\n return this;\r\n }\r\n\r\n public withProcessEnv(): ConfigLoader {\r\n this.processEnv = {\r\n NODE_ENV: process.env['NODE_ENV'],\r\n APPDATA: process.env['APPDATA'],\r\n npm_package_version: process.env['npm_package_version'],\r\n };\r\n return this;\r\n }\r\n\r\n public withArgv(argv: ArgvContext): ConfigLoader {\r\n this.argv = argv;\r\n return this;\r\n }\r\n\r\n public withEnviromentFile(filePath: string): ConfigLoader {\r\n this.envFile = dotenv.config({ path: filePath, quiet: true });\r\n return this;\r\n }\r\n\r\n public withConfigFile(filename: string): ConfigLoader {\r\n try {\r\n const configFolder = this.getApplicationConfigFolder();\r\n const configPath = path.join(configFolder, filename);\r\n if (fs.existsSync(configPath)) {\r\n const raw = fs.readFileSync(configPath, 'utf8');\r\n const parsed = JSON.parse(raw);\r\n if (isObject(parsed) && !isArray(parsed)) {\r\n this.configFileContent = parsed as Record<string, unknown>;\r\n } else {\r\n this._notifier.warn(`Config file ${filename} does not contain a valid object`, { scope: NotifyScope.System });\r\n }\r\n }\r\n } catch (error) {\r\n // Log error but continue - config file is optional\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n this._notifier.warn(`Failed to load config file ${filename}: ${errorMessage}`, { scope: NotifyScope.System });\r\n }\r\n return this;\r\n }\r\n\r\n public build(): Configuration {\r\n // Priority: argv -> env file -> config file -> process env\r\n \r\n // Build controlBaseUrl\r\n this.config.controlBaseUrl = this.getControlBaseUrl();\r\n \r\n // Build bridgeWsUrl\r\n this.config.bridgeWsUrl = this.getBridgeWsUrl();\r\n \r\n // Build directories (array of Directory objects)\r\n this.config.directories = this.getDirectories();\r\n \r\n // Build device (Device object)\r\n this.config.device = this.getDevice();\r\n \r\n // Build tokens (only available from config file)\r\n this.config.tokens = this.getTokens();\r\n \r\n return this.config;\r\n }\r\n\r\n public getConfigValue<T>(key: string, options?: { defaultValue?: T }): T {\r\n const value = this.safeGetConfigValue<T>(key);\r\n if (value === undefined) {\r\n return options?.defaultValue as T;\r\n }\r\n return value;\r\n }\r\n\r\n private getControlBaseUrl(): string | undefined {\r\n // argv -> env file -> config file -> process env -> bundled .env.production\r\n return this.argv?.controlUrl\r\n ?? this.safeGetEnvValue('DLINK_CONTROL_URL')\r\n ?? this.safeGetConfigValue<string>('controlBaseUrl')\r\n ?? this.processEnv['DLINK_CONTROL_URL']\r\n ?? this.productionEnv['DLINK_CONTROL_URL']\r\n ?? undefined;\r\n }\r\n\r\n private getBridgeWsUrl(): string | undefined {\r\n // argv -> env file -> config file -> process env -> bundled .env.production\r\n return this.argv?.bridgeWsUrl\r\n ?? this.safeGetEnvValue('DLINK_BRIDGE_URL')\r\n ?? this.safeGetConfigValue<string>('bridgeWsUrl')\r\n ?? this.processEnv['DLINK_BRIDGE_URL']\r\n ?? this.productionEnv['DLINK_BRIDGE_URL']\r\n ?? undefined;\r\n }\r\n\r\n private getDirectories(): Directory[] {\r\n // argv -> env file -> config file -> process env\r\n \r\n // Check argv first (single path string)\r\n if (this.argv?.rootPath) {\r\n try {\r\n return this.parseDirectoriesFromString(this.argv.rootPath);\r\n } catch {\r\n // If parsing fails, try to create a single directory from the path\r\n return [this.createDirectoryFromPath(this.argv.rootPath)];\r\n }\r\n }\r\n \r\n // Check env file (support both old and new names for backward compatibility)\r\n const envDirs = this.safeGetEnvValue('DLINK_DIRECTORIES') ?? this.safeGetEnvValue('DLINK_ROOTS');\r\n if (envDirs) {\r\n try {\r\n return this.parseDirectoriesFromString(envDirs);\r\n } catch {\r\n // Ignore parse errors, continue to next source\r\n }\r\n }\r\n \r\n // Check config file (support both old and new names for backward compatibility)\r\n const configDirs = this.safeGetConfigValue<unknown>('directories') ?? this.safeGetConfigValue<unknown>('roots');\r\n if (configDirs) {\r\n try {\r\n return this.parseDirectoriesFromValue(configDirs);\r\n } catch {\r\n // Ignore parse errors, continue to next source\r\n }\r\n }\r\n \r\n // Check process env (support both old and new names for backward compatibility)\r\n const processDirs = this.processEnv['DLINK_DIRECTORIES'] ?? this.processEnv['DLINK_ROOTS'];\r\n if (processDirs) {\r\n try {\r\n return this.parseDirectoriesFromString(processDirs);\r\n } catch {\r\n // Ignore parse errors\r\n }\r\n }\r\n\r\n // Default: share the current working directory\r\n const cwd = process.cwd();\r\n return [this.createDirectoryFromPath(cwd)];\r\n }\r\n\r\n private getDevice(): Device | undefined {\r\n // Get each field individually with priority: argv -> env file -> config file -> process env\r\n \r\n // Device ID: argv -> env file -> config file -> process env -> machine id\r\n // getDeviceId() already handles machine ID fallback, so no need to try again here\r\n const deviceId = this.getDeviceId();\r\n if (!deviceId) {\r\n this._notifier.warn('No device ID found from any source (argv, env, config, process env, or machine ID)', { scope: NotifyScope.System });\r\n return undefined;\r\n }\r\n \r\n // Device name: argv -> env file -> config file -> process env -> hostname\r\n let deviceName = this.getDeviceName();\r\n if (!deviceName) {\r\n deviceName = os.hostname() || 'Unknown Device';\r\n }\r\n \r\n // Device tag: argv -> env file -> config file -> process env\r\n const deviceTag = this.getDeviceTag();\r\n \r\n // Device keys: argv -> config file -> env file -> process env -> generate (private key also from secret storage cache)\r\n const keyBuilder = new KeyBuilder({\r\n notifier: this._notifier,\r\n argv: this.argv,\r\n envFile: this.envFile,\r\n processEnv: this.processEnv,\r\n configFileContent: this.configFileContent,\r\n getPrivateKey: () => this._privateKeyCache,\r\n });\r\n const { publicKey } = keyBuilder.ensureDeviceKeys();\r\n this._privateKeyToStore = keyBuilder.getLastGeneratedPrivateKey();\r\n \r\n const device: Device = {\r\n id: deviceId,\r\n name: deviceName,\r\n tag: deviceTag || '',\r\n keys: {\r\n public: publicKey,\r\n },\r\n };\r\n \r\n this._notifier.info(`Created device: id=${device.id?.substring(0, 8)}..., name=${device.name}, tag=${device.tag || '(empty)'}`, { scope: NotifyScope.System });\r\n \r\n return device;\r\n }\r\n\r\n private getDeviceId(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env -> machine id\r\n // Note: ArgvContext doesn't have deviceId, so skip argv\r\n \r\n this._notifier.info('Checking env file for DLINK_DEVICE_ID...', { scope: NotifyScope.System });\r\n const envId = this.safeGetEnvValue('DLINK_DEVICE_ID');\r\n if (envId && !isEmpty(envId)) {\r\n this._notifier.info(`Found device ID in env file: ${envId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return envId;\r\n }\r\n \r\n this._notifier.info('Checking config file for deviceId...', { scope: NotifyScope.System });\r\n const configId = this.safeGetConfigValue<string>('deviceId') \r\n ?? get(this.safeGetConfigValue<unknown>('device'), 'id') as string | undefined;\r\n if (configId && !isEmpty(String(configId))) {\r\n this._notifier.info(`Found device ID in config file: ${String(configId).substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return String(configId);\r\n }\r\n \r\n this._notifier.info('Checking process env for DLINK_DEVICE_ID...', { scope: NotifyScope.System });\r\n const processId = this.processEnv['DLINK_DEVICE_ID'];\r\n if (processId && !isEmpty(processId)) {\r\n this._notifier.info(`Found device ID in process env: ${processId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return processId;\r\n }\r\n \r\n // Fallback to machine ID\r\n this._notifier.info('Trying machine ID as fallback...', { scope: NotifyScope.System });\r\n const machineId = getMachineId(true);\r\n if (machineId) {\r\n this._notifier.info(`Using machine ID: ${machineId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return machineId;\r\n } else {\r\n this._notifier.error('Failed to get machine ID in getDeviceId()', { scope: NotifyScope.System });\r\n }\r\n \r\n this._notifier.warn('No device ID found in any source', { scope: NotifyScope.System });\r\n return undefined;\r\n }\r\n\r\n private getDeviceName(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env -> hostname\r\n // Note: ArgvContext doesn't have deviceName, so skip argv\r\n \r\n const envName = this.safeGetEnvValue('DLINK_DEVICE_NAME');\r\n if (envName && !isEmpty(envName)) return envName;\r\n \r\n const configName = get(this.safeGetConfigValue<unknown>('device'), 'name') as string | undefined;\r\n if (configName && !isEmpty(String(configName))) return String(configName);\r\n \r\n const processName = this.processEnv['DLINK_DEVICE_NAME'];\r\n if (processName && !isEmpty(processName)) return processName;\r\n \r\n // Fallback to hostname\r\n const hostname = os.hostname();\r\n if (hostname && !isEmpty(hostname)) return hostname;\r\n \r\n return undefined;\r\n }\r\n\r\n private getDeviceTag(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env\r\n // Note: ArgvContext doesn't have deviceTag, so skip argv\r\n \r\n const envTag = this.safeGetEnvValue('DLINK_DEVICE_TAG');\r\n if (envTag) return envTag;\r\n \r\n const configTag = get(this.safeGetConfigValue<unknown>('device'), 'tag') as string | undefined;\r\n if (configTag) return String(configTag);\r\n \r\n const processTag = this.processEnv['DLINK_DEVICE_TAG'];\r\n if (processTag) return processTag;\r\n \r\n return undefined;\r\n }\r\n\r\n private getTokens(): Tokens | undefined {\r\n // Tokens are only available from config file (as per user requirement)\r\n const configTokens = this.safeGetConfigValue<unknown>('tokens');\r\n if (!configTokens || !isObject(configTokens) || isArray(configTokens)) {\r\n return undefined;\r\n }\r\n \r\n const tokensObj = configTokens as Record<string, unknown>;\r\n const tokens: Tokens = {};\r\n \r\n const accessTokenExpSec = get(tokensObj, 'accessTokenExpSec');\r\n if (typeof accessTokenExpSec === 'number') {\r\n tokens.accessTokenExpSec = accessTokenExpSec;\r\n }\r\n \r\n if (tokens.accessTokenExpSec !== undefined) {\r\n return tokens;\r\n }\r\n \r\n return undefined;\r\n }\r\n\r\n\r\n private safeGetEnvValue(key: string): string | undefined {\r\n try {\r\n return get(this.envFile, `parsed.${key}`) as string | undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private safeGetConfigValue<T>(key: string): T | undefined {\r\n try {\r\n return get(this.configFileContent, key) as T | undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private parseDirectoriesFromString(value: string): Directory[] {\r\n // Try to parse as JSON first\r\n try {\r\n const parsed = JSON.parse(value);\r\n return this.parseDirectoriesFromValue(parsed);\r\n } catch {\r\n // If not JSON, treat as single path string\r\n return [this.createDirectoryFromPath(value)];\r\n }\r\n }\r\n\r\n private parseDirectoriesFromValue(value: unknown): Directory[] {\r\n if (isArray(value)) {\r\n return value\r\n .map((item) => this.parseDirectoryFromValue(item))\r\n .filter((directory): directory is Directory => directory !== null);\r\n }\r\n \r\n if (isString(value)) {\r\n return [this.createDirectoryFromPath(value)];\r\n }\r\n \r\n // Try to parse as single Directory object\r\n const directory = this.parseDirectoryFromValue(value);\r\n return directory ? [directory] : [];\r\n }\r\n\r\n private parseDirectoryFromValue(value: unknown): Directory | null {\r\n if (isString(value)) {\r\n return this.createDirectoryFromPath(value);\r\n }\r\n \r\n if (isObject(value) && !isArray(value)) {\r\n const obj = value as Record<string, unknown>;\r\n const id = (pathToUuidLikeSha256(get(obj, 'path') as string));\r\n const directoryPath = get(obj, 'path') as string;\r\n const name = defaultTo(\r\n get(obj, 'name'),\r\n directoryPath ? path.basename(directoryPath) : ''\r\n ) as string;\r\n \r\n if (!isEmpty(id) && !isEmpty(directoryPath)) {\r\n const tag = getDirectoryTag(directoryPath);\r\n return { \r\n id: String(id), \r\n name: String(name), \r\n path: String(directoryPath),\r\n tag\r\n };\r\n }\r\n }\r\n \r\n return null;\r\n }\r\n\r\n private createDirectoryFromPath(directoryPath: string): Directory {\r\n const normalizedPath = path.resolve(directoryPath);\r\n const id = pathToUuidLikeSha256(normalizedPath);\r\n const name = path.basename(normalizedPath);\r\n const tag = getDirectoryTag(normalizedPath);\r\n return { id, name, path: normalizedPath, tag };\r\n }\r\n\r\n private getApplicationConfigFolder(): string {\r\n const appData = defaultTo(\r\n this.processEnv['APPDATA'],\r\n path.join(os.homedir(), 'AppData', 'Roaming')\r\n );\r\n return path.join(appData, 'DeviceLink');\r\n }\r\n}", "import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\nconst nodeMachineId = require('node-machine-id');\n\n/**\n * Get the machine ID synchronously.\n * Uses the original (non-hashed) value by default.\n * @param original - If true, return original value; if false, return hashed value (default: true)\n * @returns Machine ID string, or undefined if retrieval fails\n */\nexport function getMachineId(original: boolean = true): string | undefined {\n try {\n const machineId = nodeMachineId.machineIdSync(original);\n if (machineId && typeof machineId === 'string' && machineId.trim().length > 0) {\n return machineId.trim();\n }\n } catch {\n // Ignore errors\n }\n return undefined;\n}\n", "import path from 'node:path';\nimport os from 'node:os';\nimport fs from 'node:fs';\nimport crypto from 'node:crypto';\nimport { ArgvContext } from '../core/context';\nimport dotenv from 'dotenv';\nimport get from 'lodash/get.js';\nimport isEmpty from 'lodash/isEmpty.js';\nimport { Notifier } from '../core/notifier';\nimport { NotifyScope } from '../core/types';\n\ntype ProcessEnv = {\n [key: string]: string | undefined;\n};\n\nexport type DeviceKeys = {\n publicKey: string;\n privateKey: string;\n};\n\nexport class KeyBuilder {\n private readonly _notifier: Notifier;\n private readonly argv?: ArgvContext;\n private readonly envFile: dotenv.DotenvConfigOutput;\n private readonly processEnv: ProcessEnv;\n private readonly configFileContent: Record<string, unknown>;\n private readonly getPrivateKey?: () => string | undefined;\n private _lastGeneratedPrivateKey?: string;\n\n public constructor(params: {\n notifier: Notifier;\n argv?: ArgvContext;\n envFile: dotenv.DotenvConfigOutput;\n processEnv: ProcessEnv;\n configFileContent: Record<string, unknown>;\n getPrivateKey?: () => string | undefined;\n }) {\n this._notifier = params.notifier;\n this.argv = params.argv;\n this.envFile = params.envFile;\n this.processEnv = params.processEnv;\n this.configFileContent = params.configFileContent;\n this.getPrivateKey = params.getPrivateKey;\n }\n\n /** Private key generated this run (when ensureDeviceKeys generated a new keypair). Caller should persist to secret storage. */\n public getLastGeneratedPrivateKey(): string | undefined {\n const key = this._lastGeneratedPrivateKey;\n this._lastGeneratedPrivateKey = undefined;\n return key;\n }\n\n /**\n * Ensures device keys are available.\n * Priority: argv -> config file -> env file -> process env -> generate new\n * Returns both keys, generating a new keypair if neither is found.\n */\n public ensureDeviceKeys(): DeviceKeys {\n // Try to get keys from various sources\n let privateKey = this.getDevicePrivateKey();\n let publicKey = this.getDevicePublicKey();\n \n // If we have both keys, return them\n if (privateKey && publicKey) {\n return { publicKey, privateKey };\n }\n \n // If we have private key but not public, derive public from private\n if (privateKey && !publicKey) {\n try {\n const privateKeyObj = crypto.createPrivateKey(privateKey);\n const publicKeyObj = crypto.createPublicKey(privateKeyObj);\n publicKey = publicKeyObj.export({ format: 'pem', type: 'spki' }).toString('utf8');\n this._notifier.info('Derived public key from private key', { scope: NotifyScope.System });\n return { publicKey, privateKey };\n } catch (e) {\n this._notifier.warn('Failed to derive public key from private key, generating new keypair', { scope: NotifyScope.System });\n }\n }\n \n // If we have public key but not private, we can't derive private, so generate new\n if (publicKey && !privateKey) {\n this._notifier.warn('Public key found but no private key, generating new keypair', { scope: NotifyScope.System });\n }\n \n // Generate new Ed25519 keypair\n this._notifier.info('Generating new Ed25519 keypair...', { scope: NotifyScope.System });\n const { publicKey: pubKey, privateKey: privKey } = crypto.generateKeyPairSync('ed25519');\n const publicKeyPem = pubKey.export({ format: 'pem', type: 'spki' }).toString('utf8');\n const privateKeyPem = privKey.export({ format: 'pem', type: 'pkcs8' }).toString('utf8');\n this._lastGeneratedPrivateKey = privateKeyPem;\n this._notifier.info('Generated new Ed25519 keypair', { scope: NotifyScope.System });\n return { publicKey: publicKeyPem, privateKey: privateKeyPem };\n }\n\n private getDevicePrivateKey(): string | undefined {\n // Priority: secret storage cache (set by LoadConfig job) -> argv (file) -> env file -> process env (config file no longer used)\n if (this.getPrivateKey) {\n const cached = this.getPrivateKey();\n if (cached && !isEmpty(cached)) {\n this._notifier.info('Using private key from secret storage cache', { scope: NotifyScope.System });\n return cached;\n }\n }\n\n // Check argv first (always a file path)\n if (this.argv?.privateKeyFile) {\n const key = this.loadKeyFromFile(this.argv.privateKeyFile);\n if (key) {\n this._notifier.info(`Found private key from --private-key-file: ${this.argv.privateKeyFile}`, { scope: NotifyScope.System });\n return key;\n } else {\n this._notifier.warn(`Failed to load private key from file: ${this.argv.privateKeyFile}`, { scope: NotifyScope.System });\n }\n }\n \n // Check env file\n const envKey = this.safeGetEnvValue('DLINK_DEVICE_PRIVATE_KEY');\n if (envKey && !isEmpty(envKey)) {\n this._notifier.info('Found private key in env file', { scope: NotifyScope.System });\n return envKey;\n }\n \n // Check process env\n const processKey = this.processEnv['DLINK_DEVICE_PRIVATE_KEY'];\n if (processKey && !isEmpty(processKey)) {\n this._notifier.info('Found private key in process env', { scope: NotifyScope.System });\n return processKey;\n }\n \n return undefined;\n }\n\n private getDevicePublicKey(): string | undefined {\n // Priority: argv (file) -> config file -> env file -> process env\n \n // Check argv first (always a file path)\n if (this.argv?.publicKeyFile) {\n const key = this.loadKeyFromFile(this.argv.publicKeyFile);\n if (key) {\n this._notifier.info(`Found public key from --public-key-file: ${this.argv.publicKeyFile}`, { scope: NotifyScope.System });\n return key;\n } else {\n this._notifier.warn(`Failed to load public key from file: ${this.argv.publicKeyFile}`, { scope: NotifyScope.System });\n }\n }\n \n // Check config file\n const configKey = get(this.safeGetConfigValue<unknown>('device'), 'keys.public') as string | undefined;\n if (configKey && !isEmpty(String(configKey))) {\n this._notifier.info('Found public key in config file', { scope: NotifyScope.System });\n return String(configKey);\n }\n \n // Check env file\n const envKey = this.safeGetEnvValue('DLINK_DEVICE_PUBLIC_KEY');\n if (envKey && !isEmpty(envKey)) {\n this._notifier.info('Found public key in env file', { scope: NotifyScope.System });\n return envKey;\n }\n \n // Check process env\n const processKey = this.processEnv['DLINK_DEVICE_PUBLIC_KEY'];\n if (processKey && !isEmpty(processKey)) {\n this._notifier.info('Found public key in process env', { scope: NotifyScope.System });\n return processKey;\n }\n \n return undefined;\n }\n\n /**\n * Loads a key from a file path.\n * Tries multiple path resolutions:\n * 1. Absolute path or relative to CWD\n * 2. Relative to config directory\n */\n private loadKeyFromFile(filePath: string): string | undefined {\n if (!filePath || isEmpty(filePath)) {\n return undefined;\n }\n \n const configFolder = this.getApplicationConfigFolder();\n const possiblePaths = [\n filePath, // Absolute path or relative to CWD\n path.join(configFolder, filePath), // Relative to config directory\n ];\n \n for (const keyPath of possiblePaths) {\n try {\n const resolvedPath = path.resolve(keyPath);\n if (fs.existsSync(resolvedPath)) {\n const stat = fs.statSync(resolvedPath);\n if (stat.isFile()) {\n const keyContent = fs.readFileSync(resolvedPath, 'utf8').trim();\n if (!isEmpty(keyContent)) {\n this._notifier.info(`Loaded key from file: ${resolvedPath}`, { scope: NotifyScope.System });\n return keyContent;\n } else {\n this._notifier.warn(`Key file is empty: ${resolvedPath}`, { scope: NotifyScope.System });\n }\n } else {\n this._notifier.warn(`Path is not a file: ${resolvedPath}`, { scope: NotifyScope.System });\n }\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this._notifier.warn(`Failed to read key file ${keyPath}: ${errorMsg}`, { scope: NotifyScope.System });\n }\n }\n \n this._notifier.warn(`Key file not found: ${filePath} (tried: ${possiblePaths.join(', ')})`, { scope: NotifyScope.System });\n return undefined;\n }\n\n private safeGetEnvValue(key: string): string | undefined {\n try {\n return get(this.envFile, `parsed.${key}`) as string | undefined;\n } catch {\n return undefined;\n }\n }\n\n private safeGetConfigValue<T>(key: string): T | undefined {\n try {\n return get(this.configFileContent, key) as T | undefined;\n } catch {\n return undefined;\n }\n }\n\n private getApplicationConfigFolder(): string {\n const appData = process.env['APPDATA'] ?? path.join(os.homedir(), 'AppData', 'Roaming');\n return path.join(appData, 'DeviceLink');\n }\n}\n", "import crypto from \"node:crypto\";\n\nfunction canonicalizePath(input: string): string {\n let s = input.trim();\n\n // 1) Unify separators to forward slash (works everywhere)\n s = s.replace(/\\\\/g, \"/\");\n\n // 2) Collapse repeated slashes (but keep leading '//' for UNC-ish paths)\n s = s.replace(/(^\\/\\/+)|\\/{2,}/g, (m, leading) => (leading ? \"//\" : \"/\"));\n\n // 3) Remove trailing slash (except root \"/\" or \"//\")\n if (s.length > 1 && s.endsWith(\"/\")) s = s.replace(/\\/+$/g, \"\");\n if (s === \"\") s = \"/\";\n\n // 4) Normalize Windows drive-letter casing: \"e:\" -> \"E:\"\n // (so e:/x and E:/x match)\n s = s.replace(/^([a-zA-Z]):(?=\\/|$)/, (_, d) => `${String(d).toUpperCase()}:`);\n\n // 5) Resolve \".\" and \"..\" purely by string rules (no filesystem access)\n const isAbs =\n s.startsWith(\"/\") ||\n s.startsWith(\"//\") ||\n /^[A-Z]:\\//.test(s); // \"E:/...\"\n\n const prefix = s.startsWith(\"//\") ? \"//\" : s.startsWith(\"/\") ? \"/\" : \"\";\n\n // For \"E:/a/b\", keep \"E:\" as a prefix token\n let drive = \"\";\n const driveMatch = s.match(/^([A-Z]:)(\\/|$)/);\n if (driveMatch) {\n drive = driveMatch[1];\n s = s.slice(drive.length);\n if (s.startsWith(\"/\")) s = s.slice(1);\n } else {\n s = s.replace(/^\\/+/, \"\"); // remove leading slashes for splitting\n }\n\n const parts = s.split(\"/\").filter(Boolean);\n const stack: string[] = [];\n\n for (const p of parts) {\n if (p === \".\") continue;\n if (p === \"..\") {\n if (stack.length > 0 && stack[stack.length - 1] !== \"..\") {\n stack.pop();\n } else if (!isAbs) {\n // relative path can keep leading \"..\"\n stack.push(\"..\");\n }\n continue;\n }\n stack.push(p);\n }\n\n let out = stack.join(\"/\");\n if (drive) out = `${drive}/${out}`.replace(/\\/+$/g, \"\");\n else if (isAbs) out = `${prefix}${out}`.replace(/\\/+$/g, \"\");\n\n // 6) Final: case normalization (optional but usually desirable)\n // If you want case-sensitive behavior, REMOVE the next line.\n out = out.toLowerCase();\n\n return out;\n}\n\nexport function getDirectoryTag(\n path: string,\n groups: number[] = [3, 3, 3, 3]\n): string {\n const canonical = canonicalizePath(path);\n\n const hash = crypto\n .createHash(\"sha256\")\n .update(canonical, \"utf8\")\n .digest(\"base64url\"); // url-safe\n\n const clean = hash.replace(/[^a-zA-Z0-9]/g, \"\").toLowerCase();\n\n const needed = groups.reduce((a, b) => a + b, 0);\n const padded = clean.length >= needed ? clean : clean.padEnd(needed, clean);\n\n let i = 0;\n return groups.map((len) => padded.slice(i, (i += len))).join(\"-\");\n}\n\nexport function pathToUuidLikeSha256(path: string): string {\n const canonical = canonicalizePath(path);\n\n const hex = crypto.createHash(\"sha256\").update(canonical, \"utf8\").digest(\"hex\");\n // take first 32 hex chars (16 bytes) and format like UUID\n const h = hex.slice(0, 32);\n\n const part1 = h.slice(0, 8);\n const part2 = h.slice(8, 12);\n const part3 = h.slice(12, 16);\n const part4 = h.slice(16, 20);\n const part5 = h.slice(20, 32);\n return `${part1}-${part2}-${part3}-${part4}-${part5}`;\n}\n", "import { EngineEventMap } from \"./events\";\n\nexport interface Subscription {\n unsubscribe(): void;\n}\n\nexport class EventBus<TEvents> {\n private readonly handlers: Map<keyof TEvents, Array<(payload: TEvents[keyof TEvents]) => void>>;\n\n public constructor() {\n this.handlers = new Map();\n }\n\n public on<K extends keyof TEvents>(event: K, handler: (payload: TEvents[K]) => void): Subscription {\n const existing = this.handlers.get(event);\n const list = existing ? existing : [];\n list.push(handler as (payload: TEvents[keyof TEvents]) => void);\n this.handlers.set(event, list);\n\n return {\n unsubscribe: () => {\n const current = this.handlers.get(event);\n if (!current) return;\n const next = current.filter((h) => h !== (handler as (payload: TEvents[keyof TEvents]) => void));\n this.handlers.set(event, next);\n },\n };\n }\n\n public emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n const list = this.handlers.get(event);\n if (!list) return;\n for (const h of list) {\n (h as (p: TEvents[K]) => void)(payload);\n }\n }\n}\n\n// convenience alias\nexport type EngineBus = EventBus<EngineEventMap>;\n", "import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { getMachineId } from \"../cli/utils/machine-id.js\";\nimport defaultTo from \"lodash/defaultTo.js\";\n\nconst SALT = \"DeviceLink-SecretStorage-v1\";\nconst IV_LENGTH = 12;\nconst TAG_LENGTH = 16;\nconst KEY_LEN = 32;\nconst SECRETS_FILENAME = \"secrets.enc.json\";\n\nexport type GetResult = { ok: true; value: string } | { ok: false };\n\nexport interface BaseStorage {\n get(key: string): Promise<GetResult>;\n set(key: string, value: string): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nfunction getSecretsPath(): string {\n const appData = defaultTo(\n process.env[\"APPDATA\"],\n path.join(os.homedir(), \"AppData\", \"Roaming\")\n );\n return path.join(appData, \"DeviceLink\", SECRETS_FILENAME);\n}\n\nfunction deriveKey(machineId: string): Buffer {\n return crypto.pbkdf2Sync(\n machineId,\n SALT,\n 100000,\n KEY_LEN,\n \"sha256\"\n );\n}\n\nexport class EncryptedFileStorage implements BaseStorage {\n private readonly secretsPath: string;\n private readonly key: Buffer;\n private cache: Record<string, string> = {};\n private loaded = false;\n\n constructor(secretsPath: string, key: Buffer) {\n this.secretsPath = secretsPath;\n this.key = key;\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await fs.readFile(this.secretsPath, \"utf8\");\n const decrypted = this.decrypt(raw);\n this.cache = JSON.parse(decrypted) as Record<string, string>;\n } catch {\n this.cache = {};\n }\n this.loaded = true;\n }\n\n private async save(): Promise<void> {\n await fs.mkdir(path.dirname(this.secretsPath), { recursive: true });\n const plain = JSON.stringify(this.cache);\n const encrypted = this.encrypt(plain);\n const tmp = this.secretsPath + \".tmp\";\n await fs.writeFile(tmp, encrypted, \"utf8\");\n await fs.rename(tmp, this.secretsPath);\n }\n\n private encrypt(plain: string): string {\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv(\"aes-256-gcm\", this.key, iv, {\n authTagLength: TAG_LENGTH,\n });\n const enc = Buffer.concat([\n cipher.update(plain, \"utf8\"),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, enc]).toString(\"base64url\");\n }\n\n private decrypt(b64: string): string {\n const buf = Buffer.from(b64, \"base64url\");\n const iv = buf.subarray(0, IV_LENGTH);\n const tag = buf.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);\n const enc = buf.subarray(IV_LENGTH + TAG_LENGTH);\n const decipher = crypto.createDecipheriv(\"aes-256-gcm\", this.key, iv, {\n authTagLength: TAG_LENGTH,\n });\n decipher.setAuthTag(tag);\n return decipher.update(enc) + decipher.final(\"utf8\");\n }\n\n async get(key: string): Promise<GetResult> {\n await this.load();\n const value = this.cache[key];\n if (value === undefined) return { ok: false };\n return { ok: true, value };\n }\n\n async set(key: string, value: string): Promise<void> {\n await this.load();\n this.cache[key] = value;\n await this.save();\n }\n\n async delete(key: string): Promise<void> {\n await this.load();\n if (this.cache[key] !== undefined) {\n delete this.cache[key];\n await this.save();\n }\n }\n}\n\n/**\n * Creates the default secret storage (encrypted file under DeviceLink config folder).\n * Uses machine ID for key derivation. No plaintext secrets on disk.\n */\nexport async function createStorage(): Promise<BaseStorage> {\n const machineId = getMachineId(true);\n if (!machineId) {\n throw new Error(\"Secret storage requires machine ID\");\n }\n const key = deriveKey(machineId);\n const secretsPath = getSecretsPath();\n return new EncryptedFileStorage(secretsPath, key);\n}\n", "import fs from \"node:fs/promises\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope, NotifyKind } from \"../core/types\";\nimport { Configuration, ConfigurationContext } from \"../core/configuration\";\nimport { ConfigLoader } from \"../utils/config.builder\";\nimport type { BaseStorage } from \"../../storage/index.js\";\n\nexport class LoadConfigInput { }\n\nexport class LoadConfigOutput {\n public readonly ok: boolean;\n public readonly config: Configuration;\n\n public constructor(ok: boolean, config: Configuration) {\n this.ok = ok;\n this.config = config;\n }\n}\n\nexport class LoadConfigJob extends JobType<LoadConfigInput, LoadConfigOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"load-config\",\n lane: \"main\",\n priority: 1000,\n locks: [\"GLOBAL\"],\n maxAttempts: 3,\n cancellable: true,\n })\n );\n }\n\n public async run(input: LoadConfigInput, ctx: JobContext): Promise<LoadConfigOutput> {\n ctx.notifier.info(\"Loading configuration...\");\n\n const configLoader = ctx.engine.configurationContext.loader;\n\n const refreshRes = await ctx.engine.secrets.get(\"devicePrivateKey\");\n configLoader.setPrivateKeyCache(refreshRes.ok && refreshRes.value ? refreshRes.value : undefined);\n\n configLoader.withDefaultConfig();\n configLoader.withArgv(ctx.engine.argv);\n\n if (ctx.engine.argv.enviromentFile) {\n configLoader.withEnviromentFile(ctx.engine.argv.enviromentFile);\n }\n configLoader.withConfigFile('config.json');\n configLoader.withProcessEnv();\n const config = configLoader.build();\n\n const privateKeyToStore = configLoader.getPrivateKeyToStore();\n if (privateKeyToStore) {\n await ctx.engine.secrets.set(\"devicePrivateKey\", privateKeyToStore);\n }\n\n this.updateUi(config, ctx);\n\n ctx.notifier.success(\"Configuration loaded\");\n\n ctx.engine.applyConfiguration(config);\n\n ctx.bus.emit(\"config:loaded\", config);\n return new LoadConfigOutput(true, config);\n }\n\n private updateUi(config: Configuration, ctx: JobContext): void {\n ctx.notifier.info(`Control base URL: ${config.controlBaseUrl}`);\n ctx.notifier.info(`Bridge WebSocket URL: ${config.bridgeWsUrl}`);\n ctx.notifier.info(`Directories: ${config.directories.map(directory => directory.path).join(', ')}`);\n ctx.notifier.info(`Device: ${config.device?.id}`);\n ctx.notifier.info(`Device name: ${config.device?.name}`);\n ctx.notifier.info(`Device tag: ${config.device?.tag}`);\n ctx.notifier.info(`Device keys public: ${config.device?.keys?.public ? '***' : '(none)'}`);\n }\n}\n\nexport const loadConfigJob = new LoadConfigJob();\n\n\nexport function loadConfigCall(input: LoadConfigInput): JobCall<LoadConfigInput, LoadConfigOutput> {\n return new JobCall(loadConfigJob, input);\n}\n\n", "import { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope, NotifyKind } from \"../core/types\";\nimport { ConsoleCommandInput } from \"../utils/command-job.builder\";\n\nexport class ConsoleCommandOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ConsoleCommandJob extends JobType<ConsoleCommandInput, ConsoleCommandOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"console-command\",\n lane: \"console\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(input: ConsoleCommandInput, ctx: JobContext): Promise<ConsoleCommandOutput> {\n ctx.notifier.info(`Executing console command: ${input.kind}`);\n // TODO: Implement actual command handling based on input.kind\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n ctx.notifier.info(`Console command executed: ${input.kind}`);\n ctx.notifier.success(`Console command executed: ${input.kind}`);\n return new ConsoleCommandOutput(true);\n }\n}\n\nexport const consoleCommandJob = new ConsoleCommandJob();\n\n\nexport function consoleCommandCall(input: ConsoleCommandInput): JobCall<ConsoleCommandInput, ConsoleCommandOutput> {\n return new JobCall(consoleCommandJob, input);\n}\n", "import { JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\n\nexport class ContactServerInput {\n public readonly mode: string;\n public constructor(mode: string) {\n this.mode = mode;\n }\n}\n\nexport class ContactServerOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ContactServerJob extends JobType<ContactServerInput, ContactServerOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"contact-server\",\n lane: \"main\",\n priority: 900,\n locks: [\"GLOBAL\"],\n maxAttempts: 8,\n cancellable: true,\n })\n );\n }\n\n public async run(input: ContactServerInput, ctx: JobContext): Promise<ContactServerOutput> {\n ctx.notifier.info(`contact server mode=${input.mode}`, { scope: NotifyScope.System });\n\n // TODO: real connection; respect ctx.signal for cancellation\n await new Promise<void>((resolve) => setTimeout(resolve, 200));\n\n return new ContactServerOutput(true);\n }\n}\n\nexport const contactServerJob = new ContactServerJob();\n", "import { JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\n\nexport class SendServerResultInput {\n public readonly requestId: string;\n public readonly resultJson: string;\n\n public constructor(requestId: string, resultJson: string) {\n this.requestId = requestId;\n this.resultJson = resultJson;\n }\n}\n\nexport class SendServerResultOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class SendServerResultJob extends JobType<SendServerResultInput, SendServerResultOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"send-server-result\",\n lane: \"io\",\n priority: 200,\n locks: [],\n maxAttempts: 10,\n cancellable: true,\n })\n );\n }\n\n public async run(input: SendServerResultInput, ctx: JobContext): Promise<SendServerResultOutput> {\n ctx.notifier.info(`send result requestId=${input.requestId}`, { scope: NotifyScope.System });\n\n // TODO: send via WS outbound channel, respect ctx.signal\n await new Promise<void>((resolve) => setTimeout(resolve, 10));\n\n return new SendServerResultOutput(true);\n }\n}\n\nexport const sendServerResultJob = new SendServerResultJob();\n", "import crypto from \"node:crypto\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\nimport { Api } from \"../api\";\nimport type { FetchError } from \"../api/api.call\";\nimport { signRefresh } from \"@devicelink-workspace/common\";\nimport {\n DeviceAuthRefreshResponse,\n DeviceAuthRefreshSuccessResponse,\n} from \"@devicelink-workspace/domain\";\nimport type { BaseStorage } from \"../../storage/index.js\";\n\n/**\n * If your HTTP handler wraps like { ok:true, data:{...} }\n * this matches the common pattern without using `any`.\n */\ntype WrappedOk = { ok: true; data: DeviceAuthRefreshSuccessResponse };\n\nfunction isWrappedOk(x: unknown): x is WrappedOk {\n if (typeof x !== \"object\" || x === null) return false;\n const r = x as Record<string, unknown>;\n if (r[\"ok\"] !== true) return false;\n const data = r[\"data\"];\n if (typeof data !== \"object\" || data === null) return false;\n\n const d = data as Record<string, unknown>;\n return (\n d[\"ok\"] === true &&\n typeof d[\"access_token\"] === \"string\" &&\n typeof d[\"refresh_token\"] === \"string\" &&\n typeof d[\"expires_in_sec\"] === \"number\" &&\n typeof d[\"device_id\"] === \"string\"\n );\n}\n\nfunction isUnwrappedOk(x: DeviceAuthRefreshResponse): x is DeviceAuthRefreshSuccessResponse {\n return (\n (x as unknown as Record<string, unknown>)[\"ok\"] === true &&\n typeof (x as unknown as Record<string, unknown>)[\"access_token\"] === \"string\"\n );\n}\n\nexport class RefreshTokensInput {\n public constructor(public readonly reason: string) {}\n}\n\n/** Server error codes that mean \"refresh token no longer valid, user must sign in again\" (no retry). */\nexport const REFRESH_UNRECOVERABLE_CODES = ['REFRESH_EXPIRED', 'REFRESH_REVOKED', 'REFRESH_NOT_FOUND'] as const;\n\nexport class RefreshTokensOutput {\n public constructor(\n public readonly ok: boolean,\n public readonly accessToken?: string,\n public readonly refreshToken?: string,\n public readonly expiresInSec?: number,\n public readonly error?: string,\n public readonly retryAfterSec?: number,\n public readonly errorCode?: string\n ) {}\n}\n\nexport class RefreshTokensJob extends JobType<RefreshTokensInput, RefreshTokensOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"refresh-tokens\",\n lane: \"io\",\n priority: 900,\n locks: [\"AUTH_REFRESH\"],\n maxAttempts: 5,\n cancellable: true,\n })\n );\n }\n\n public async run(input: RefreshTokensInput, ctx: JobContext): Promise<RefreshTokensOutput> {\n const cfg = ctx.engine.configurationContext.configuration;\n\n if (!cfg.controlBaseUrl) return new RefreshTokensOutput(false, undefined, undefined, undefined, \"controlBaseUrl missing\");\n if (!cfg.device?.id) return new RefreshTokensOutput(false, undefined, undefined, undefined, \"device.id missing\");\n\n const privateRes = await ctx.engine.secrets.get(\"devicePrivateKey\");\n if (!privateRes.ok || !privateRes.value) {\n return new RefreshTokensOutput(false, undefined, undefined, undefined, \"device private key missing\");\n }\n const privateKeyPem = privateRes.value;\n\n const refreshRes = await ctx.engine.secrets.get(\"refreshToken\");\n if (!refreshRes.ok || !refreshRes.value) {\n return new RefreshTokensOutput(false, undefined, undefined, undefined, \"refresh token missing\");\n }\n const refreshToken = refreshRes.value;\n\n ctx.notifier.info(`Refreshing tokens (job) reason=${input.reason}`, { scope: NotifyScope.System, category: ['token-refresh'] });\n\n const ts = Date.now();\n const nonce = crypto.randomBytes(16).toString(\"base64url\");\n const sig = signRefresh({\n deviceId: cfg.device.id,\n ts,\n nonce,\n refreshToken,\n privateKeyPem,\n });\n\n const api = new Api(cfg, ctx.notifier);\n\n let raw: unknown;\n try {\n raw = await api.deviceAuthRefresh({\n device_id: cfg.device.id,\n refresh_token: refreshToken,\n ts,\n nonce,\n sig,\n });\n } catch (e: unknown) {\n const err = e instanceof Error ? e.message : String(e);\n const fetchErr = e as FetchError;\n const retryAfterSec = fetchErr.retryAfterSec;\n const status = fetchErr.status;\n const body = fetchErr.body as Record<string, unknown> | undefined;\n const errObj = body != null ? (body as Record<string, unknown>)['error'] : undefined;\n const errorCode =\n status === 401 &&\n errObj != null &&\n typeof errObj === 'object' &&\n (errObj as Record<string, unknown>)['code'] === 'REFRESH_NOT_FOUND'\n ? 'REFRESH_NOT_FOUND'\n : undefined;\n if (errorCode === 'REFRESH_NOT_FOUND') {\n ctx.notifier.warn(\n 'Refresh token not found; clearing stored refresh token and stopping automatic refresh. Please run signin.',\n { category: ['token-refresh'] }\n );\n\n // Critical: clear invalid refresh token so we stop retrying forever\n await ctx.engine.secrets.delete('refreshToken').catch(() => {});\n\n return new RefreshTokensOutput(\n false,\n undefined,\n undefined,\n undefined,\n 'Refresh token not found',\n undefined,\n 'REFRESH_NOT_FOUND'\n );\n }\n ctx.notifier.error(`Refresh tokens failed: ${err}`, { category: ['token-refresh'] });\n return new RefreshTokensOutput(false, undefined, undefined, undefined, err, retryAfterSec, errorCode);\n }\n\n const normalized: DeviceAuthRefreshSuccessResponse | null = this.normalizeRefreshResponse(raw);\n\n if (!normalized) {\n const err = this.extractErrorMessage(raw);\n const errorCode = this.extractErrorCode(raw);\n ctx.notifier.error(`Refresh tokens failed: ${err}`, { category: ['token-refresh'] });\n return new RefreshTokensOutput(false, undefined, undefined, undefined, err, undefined, errorCode);\n }\n\n if (normalized.refresh_token) {\n await ctx.engine.secrets.set(\"refreshToken\", normalized.refresh_token);\n }\n\n return new RefreshTokensOutput(true, normalized.access_token, normalized.refresh_token, normalized.expires_in_sec);\n }\n\n private normalizeRefreshResponse(\n raw: unknown\n ): DeviceAuthRefreshSuccessResponse | null {\n // Wrapped controller response\n if (isWrappedOk(raw)) return raw.data;\n\n // Domain response (unwrapped)\n if (this.looksLikeDomainRefresh(raw)) {\n const r = raw as DeviceAuthRefreshResponse;\n if (isUnwrappedOk(r)) return r;\n return null;\n }\n\n return null;\n }\n\n private looksLikeDomainRefresh(raw: unknown): raw is DeviceAuthRefreshResponse {\n if (typeof raw !== \"object\" || raw === null) return false;\n const r = raw as Record<string, unknown>;\n return r[\"ok\"] === true || r[\"ok\"] === false;\n }\n\n private extractErrorMessage(raw: unknown): string {\n if (typeof raw !== \"object\" || raw === null) return \"Unknown error\";\n const r = raw as Record<string, unknown>;\n\n // wrapped error: { ok:false, error:{message} }\n if (r[\"ok\"] === false) {\n const err = r[\"error\"];\n if (typeof err === \"object\" && err !== null) {\n const e = err as Record<string, unknown>;\n const msg = e[\"message\"];\n if (typeof msg === \"string\" && msg.length > 0) return msg;\n }\n }\n\n // wrapped ok but missing data\n if (r[\"ok\"] === true && \"data\" in r) return \"Bad refresh response: missing token fields\";\n\n return \"Unknown error\";\n }\n\n private extractErrorCode(raw: unknown): string | undefined {\n if (typeof raw !== \"object\" || raw === null) return undefined;\n const r = raw as Record<string, unknown>;\n if (r[\"ok\"] !== false) return undefined;\n const err = r[\"error\"];\n if (typeof err !== \"object\" || err === null) return undefined;\n const code = (err as Record<string, unknown>)[\"code\"];\n return typeof code === \"string\" ? code : undefined;\n }\n}\n\nexport const refreshTokensJob = new RefreshTokensJob();\n\nexport function refreshTokensCall(input: RefreshTokensInput): JobCall<RefreshTokensInput, RefreshTokensOutput> {\n return new JobCall(refreshTokensJob, input);\n}\n", "import { Configuration } from '../core/configuration';\r\nimport { Notifier } from '../core/notifier';\r\n\r\nexport type ApiCallContext = {\r\n configuration: Configuration;\r\n notifier: Notifier;\r\n};\r\n\r\ntype Handler<Input, Output> = (\r\n context: ApiCallContext,\r\n input: Input,\r\n) => Promise<Output>;\r\n\r\nexport class ApiCall<Input, Output> {\r\n constructor(\r\n private readonly context: ApiCallContext,\r\n private readonly handler: Handler<Input, Output>,\r\n ) {}\r\n\r\n execute(input: Input): Promise<Output> {\r\n return this.handler(this.context, input);\r\n }\r\n}\r\n\r\nexport type FetchError = Error & {\r\n retryAfterSec?: number;\r\n status?: number;\r\n body?: unknown;\r\n};\r\n\r\nexport async function fetchJson<T>(\r\n context: ApiCallContext,\r\n path: string,\r\n init: RequestInit,\r\n): Promise<T> {\r\n const url = `${context.configuration.controlBaseUrl}${path}`;\r\n const res = await fetch(url, init);\r\n\r\n if (!res.ok) {\r\n const text = await res.text().catch(() => '');\r\n const err = new Error(`HTTP ${res.status}: ${text}`) as FetchError;\r\n err.status = res.status;\r\n try {\r\n err.body = text ? (JSON.parse(text) as unknown) : undefined;\r\n } catch {\r\n err.body = undefined;\r\n }\r\n if (res.status === 429) {\r\n const retryAfter = res.headers.get('Retry-After');\r\n if (retryAfter !== null) {\r\n const sec = parseInt(retryAfter, 10);\r\n if (Number.isFinite(sec) && sec >= 0) err.retryAfterSec = sec;\r\n }\r\n }\r\n throw err;\r\n }\r\n\r\n return res.json() as Promise<T>;\r\n}\r\n", "import { z } from 'zod';\nimport { ApiCall, ApiCallContext, fetchJson } from '../api.call';\nimport type { DeviceAuthStartRequest, DeviceAuthStartResponse } from '@devicelink-workspace/domain';\n\nexport function makeDeviceAuthStart(context: ApiCallContext) {\n return new ApiCall<DeviceAuthStartRequest, DeviceAuthStartResponse>(\n context,\n async (c, input) => {\n return fetchJson<DeviceAuthStartResponse>(c, '/api/device/authorize/start', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n });\n },\n );\n}\n", "import { z } from 'zod';\nimport { ApiCall, ApiCallContext, fetchJson } from '../api.call';\nimport type { DeviceAuthProveRequest, DeviceAuthProveResponse } from '@devicelink-workspace/domain';\n\nexport function makeDeviceAuthProve(context: ApiCallContext) {\n return new ApiCall<DeviceAuthProveRequest, DeviceAuthProveResponse>(\n context,\n async (c, input) => {\n return fetchJson<DeviceAuthProveResponse>(c, '/api/device/authorize/prove', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n });\n },\n );\n}\n", "import { ApiCall, ApiCallContext } from \"../api.call\";\nimport { NotifyScope } from \"../../core/types\";\nimport { z } from \"zod\";\nimport type {\n DeviceAuthStreamRequest,\n DeviceAuthStreamResponse,\n} from \"@devicelink-workspace/domain\";\n\nconst DeviceAuthStreamResponseSchema = z.union([\n z.object({\n status: z.literal(\"pending\"),\n needs_proof: z.boolean(),\n }),\n z.object({\n status: z.literal(\"approved\"),\n needs_proof: z.boolean(),\n }),\n z.object({\n error: z.literal(\"access_denied\"),\n }),\n z.object({\n error: z.literal(\"expired_token\"),\n }),\n]);\n\n/**\n * makeDeviceAuthStream\n * Waits for SSE events from Control. Returns only status snapshots/errors:\n * - pending: { status: \"pending\", needs_proof: boolean }\n * - approved: { status: \"approved\", needs_proof: boolean }\n * - denied: { error: \"access_denied\" }\n * - expired: { error: \"expired_token\" }\n */\nexport function makeDeviceAuthStream(context: ApiCallContext) {\n return new ApiCall<DeviceAuthStreamRequest, DeviceAuthStreamResponse>(\n context,\n async (c, input) => {\n const url = new URL(\"/api/device/authorize/stream\", c.configuration.controlBaseUrl);\n url.searchParams.set(\"device_code\", input.deviceCode);\n const notifier = c.notifier;\n\n const controller = new AbortController();\n const t = setTimeout(() => {\n notifier.error(`[deviceAuthStream] Timeout reached, aborting`);\n controller.abort();\n }, Math.max(1000, input.timeoutMs));\n\n if (input.signal) {\n input.signal.addEventListener(\"abort\", () => {\n notifier.warn(\n `[deviceAuthStream] External signal aborted: ${String((input.signal as any)?.reason ?? \"\")}`,\n );\n controller.abort();\n });\n }\n\n try {\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { Accept: \"text/event-stream\" },\n signal: controller.signal,\n });\n\n if (!res.ok || !res.body) {\n const text = await res.text().catch(() => \"\");\n notifier.error(\n `[deviceAuthStream] Response error: ${res.status} - ${text}`,\n );\n throw new Error(`device/authorize/stream failed (${res.status}): ${text}`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buf = \"\";\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n notifier.error(`[deviceAuthStream] Stream ended unexpectedly`);\n break;\n }\n\n buf += decoder.decode(value, { stream: true });\n\n while (true) {\n const idx = buf.indexOf(\"\\n\\n\");\n if (idx === -1) break;\n\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n\n let event: string | null = null;\n let dataStr: string | null = null;\n\n for (const line of raw.split(\"\\n\")) {\n if (line.startsWith(\"event:\")) event = line.slice(6).trim();\n if (line.startsWith(\"data:\")) dataStr = line.slice(5).trim();\n }\n\n // ignore keepalive / comments etc\n if (!event || !dataStr) continue;\n\n let data: unknown;\n try {\n data = JSON.parse(dataStr);\n } catch (e) {\n notifier.error(\n `[deviceAuthStream] Failed to parse event data as JSON: ${String(e)}`,\n );\n continue;\n }\n\n const parsed = DeviceAuthStreamResponseSchema.safeParse(data);\n if (!parsed.success) {\n notifier.error(\n `[deviceAuthStream] Event validation failed (${event}): ${String(parsed.error)}`,\n );\n continue;\n }\n\n const payload = parsed.data;\n\n // terminal events:\n if (event === \"approved\") return payload;\n if (event === \"denied\") return payload;\n if (event === \"expired\") return payload;\n\n // pending is non-terminal; you can log only if needs_proof is true\n if (event === \"pending\") {\n if ((payload as any)?.status === \"pending\" && (payload as any)?.needs_proof === true) {\n notifier.warn(\n `[deviceAuthStream] pending: needs_proof=true (unexpected before approval)`,\n );\n }\n continue;\n }\n\n notifier.warn(`[deviceAuthStream] Unknown event type: ${event}`);\n }\n }\n\n notifier.error(\n `[deviceAuthStream] Stream ended unexpectedly without completion`,\n );\n throw new Error(\"Device authorization stream ended without completion\");\n } catch (e: any) {\n if (e?.name === \"AbortError\") {\n notifier.warn(`[deviceAuthStream] Aborted: ${e?.message ?? \"\"}`);\n } else {\n notifier.error(`[deviceAuthStream] Error: ${e?.message ?? String(e)}`);\n }\n throw e;\n } finally {\n clearTimeout(t);\n }\n },\n );\n}\n", "import { ApiCall, ApiCallContext, fetchJson } from \"../api.call\";\r\nimport type { DeviceAuthTokenRequest, DeviceAuthTokenResponse } from \"@devicelink-workspace/domain\";\r\n\r\nexport function makeDeviceAuthToken(context: ApiCallContext) {\r\n return new ApiCall<DeviceAuthTokenRequest, DeviceAuthTokenResponse>(\r\n context,\r\n async (c, input) => {\r\n return fetchJson<DeviceAuthTokenResponse>(c, \"/api/device/authorize/token\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(input),\r\n });\r\n },\r\n );\r\n}\r\n", "import { ApiCall, ApiCallContext, fetchJson } from \"../api.call\";\r\nimport {\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse,\r\n} from \"@devicelink-workspace/domain\";\r\n\r\nexport function makeDeviceAuthRefresh(context: ApiCallContext) {\r\n return new ApiCall<DeviceAuthRefreshRequest, DeviceAuthRefreshResponse>(\r\n context,\r\n async (c, input) => {\r\n const controller = new AbortController();\r\n const timeoutMs = 30_000; // 30 second timeout\r\n const timeoutId = setTimeout(() => {\r\n controller.abort();\r\n }, timeoutMs);\r\n\r\n try {\r\n const result = await fetchJson<DeviceAuthRefreshResponse>(c, \"/api/device/authorize/refresh\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(input),\r\n signal: controller.signal,\r\n });\r\n clearTimeout(timeoutId);\r\n return result;\r\n } catch (error: unknown) {\r\n clearTimeout(timeoutId);\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new Error(`Refresh token request timed out after ${timeoutMs}ms`);\r\n }\r\n throw error;\r\n }\r\n }\r\n );\r\n}\r\n", "import { ApiCall } from './api.call';\r\nimport { makeDeviceAuthStart } from './definitions/device-auth-start.api';\r\nimport { makeDeviceAuthProve } from './definitions/device-auth-prove.api';\r\nimport { makeDeviceAuthStream } from './definitions/device-auth-stream.api';\r\nimport { makeDeviceAuthToken } from './definitions/device-auth-token.api';\r\nimport { Configuration } from '../core/configuration';\r\nimport { Notifier } from '../core/notifier';\r\nimport {\r\n DeviceAuthProveRequest,\r\n DeviceAuthProveResponse,\r\n DeviceAuthStartRequest,\r\n DeviceAuthStartResponse,\r\n DeviceAuthStreamRequest,\r\n DeviceAuthStreamResponse,\r\n DeviceAuthTokenRequest,\r\n DeviceAuthTokenResponse,\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse,\r\n} from '@devicelink-workspace/domain';\r\nimport { makeDeviceAuthRefresh } from './definitions/device-auth-refresh.api';\r\n\r\nexport class Api {\r\n private readonly deviceAuthStartCall: ApiCall<\r\n DeviceAuthStartRequest,\r\n DeviceAuthStartResponse\r\n >;\r\n private readonly deviceAuthProveCall: ApiCall<\r\n DeviceAuthProveRequest,\r\n DeviceAuthProveResponse\r\n >;\r\n private readonly deviceAuthStreamCall: ApiCall<\r\n DeviceAuthStreamRequest,\r\n DeviceAuthStreamResponse\r\n >;\r\n private readonly deviceAuthTokenCall: ApiCall<\r\n DeviceAuthTokenRequest,\r\n DeviceAuthTokenResponse\r\n >;\r\n private readonly deviceAuthRefreshCall: ApiCall<\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse\r\n >;\r\n\r\n constructor(configuration: Configuration, notifier: Notifier) {\r\n const context = { configuration, notifier };\r\n this.deviceAuthStartCall = makeDeviceAuthStart(context);\r\n this.deviceAuthProveCall = makeDeviceAuthProve(context);\r\n this.deviceAuthStreamCall = makeDeviceAuthStream(context);\r\n this.deviceAuthTokenCall = makeDeviceAuthToken(context);\r\n this.deviceAuthRefreshCall = makeDeviceAuthRefresh(context);\r\n }\r\n\r\n deviceAuthStart(input: DeviceAuthStartRequest) {\r\n return this.deviceAuthStartCall.execute(input);\r\n }\r\n\r\n deviceAuthProve(input: DeviceAuthProveRequest) {\r\n return this.deviceAuthProveCall.execute(input);\r\n }\r\n\r\n deviceAuthStream(input: DeviceAuthStreamRequest) {\r\n return this.deviceAuthStreamCall.execute(input);\r\n }\r\n\r\n deviceAuthToken(input: DeviceAuthTokenRequest) {\r\n return this.deviceAuthTokenCall.execute(input);\r\n }\r\n \r\n deviceAuthRefresh(input: DeviceAuthRefreshRequest) {\r\n return this.deviceAuthRefreshCall.execute(input);\r\n }\r\n}\r\n", "import * as crypto from 'node:crypto';\r\nimport { toCrockfordBase32 } from './format.utils';\r\nimport { formatXXXX } from './string.utils';\r\n\r\n/**\r\n * Compute SHA256 hash of a string (hex format)\r\n */\r\nexport function sha256Hex(s: string): string {\r\n return crypto.createHash('sha256').update(s).digest('hex');\r\n}\r\n\r\n/**\r\n * Generate a canonical fingerprint from public key PEM\r\n * Uses SPKI DER format for consistent hashing regardless of PEM formatting\r\n */\r\nexport function fingerprintFromPublicKeyPem(publicKeyPem: string): string {\r\n const keyObj = crypto.createPublicKey(publicKeyPem);\r\n\r\n if (keyObj.asymmetricKeyType !== 'ed25519') {\r\n throw new Error(`Unexpected key type: ${keyObj.asymmetricKeyType}`);\r\n }\r\n\r\n const spkiDer = keyObj.export({ format: 'der', type: 'spki' }) as Buffer;\r\n const hash = crypto.createHash('sha256').update(spkiDer).digest('base64url');\r\n return hash.slice(0, 16).toUpperCase();\r\n}\r\n\r\n/**\r\n * Generate memorable tag from input and salt\r\n * 16 Crockford base32 chars ~= 80 bits. Collision risk is negligible at your scale.\r\n */\r\nexport function memorableTag(input: string, salt: string): string {\r\n const digest = crypto.createHash('sha256').update(`${salt}|${input}`).digest();\r\n const b32 = toCrockfordBase32(digest);\r\n return formatXXXX(b32);\r\n}\r\n\r\n/**\r\n * Generate a new opaque refresh token\r\n * 32 random bytes base64url => ~43 chars\r\n */\r\nexport function newOpaqueToken(): string {\r\n return crypto.randomBytes(32).toString('base64url');\r\n}\r\n\r\n\r\nexport function signConnect(params: { deviceId: string; ts: number; nonce: string; privateKeyPem: string }): string {\r\n const payload = Buffer.from(`${params.deviceId}|${params.ts}|${params.nonce}`, \"utf8\");\r\n const key = crypto.createPrivateKey(params.privateKeyPem);\r\n const sig = crypto.sign(null, payload, key); // Ed25519\r\n return sig.toString(\"base64\");\r\n}\r\n\r\nexport function signRefresh(params: { deviceId: string; ts: number; nonce: string; refreshToken: string; privateKeyPem: string }): string {\r\n const hash = crypto.createHash(\"sha256\").update(params.refreshToken, \"utf8\").digest(\"hex\");\r\n const payload = Buffer.from(`${params.deviceId}|${params.ts}|${params.nonce}|${hash}`, \"utf8\");\r\n const key = crypto.createPrivateKey(params.privateKeyPem);\r\n const sig = crypto.sign(null, payload, key);\r\n return sig.toString(\"base64\");\r\n}\r\n", "/**\r\n * Sleep/delay utility\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Get current time in seconds (Unix timestamp)\r\n */\r\nexport function nowSec(): number {\r\n return Math.floor(Date.now() / 1000);\r\n}\r\n", "import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\r\nimport { Subscription } from \"../core/eventBus.js\";\r\nimport { LogEntry, JobEvent, NotifyEvent } from \"../core/events.js\";\r\n\r\nexport class TelemetryOrchestrator implements Orchestrator {\r\n public readonly name: string;\r\n\r\n private readonly filePath: string;\r\n\r\n private readonly buffer: string[];\r\n private timer: NodeJS.Timeout | null;\r\n\r\n private subs: Subscription[];\r\n\r\n public constructor(filePath: string) {\r\n this.name = \"telemetry-orchestrator\";\r\n this.filePath = filePath;\r\n\r\n this.buffer = [];\r\n this.timer = null;\r\n this.subs = [];\r\n }\r\n\r\n public onRegister(_ctx: OrchestratorContext): void {}\r\n\r\n public async onStart(ctx: OrchestratorContext): Promise<void> {\r\n this.subs.push(ctx.on(\"log\", (e) => this.onLog(e)));\r\n this.subs.push(ctx.on(\"job:event\", (e) => this.onJob(e)));\r\n this.subs.push(ctx.on(\"notify:event\", (e) => this.onNotify(e)));\r\n }\r\n\r\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\r\n return Promise.resolve();\r\n }\r\n\r\n public async onStop(_ctx: OrchestratorContext): Promise<void> {\r\n for (const s of this.subs) s.unsubscribe();\r\n this.subs = [];\r\n await this.flush();\r\n }\r\n\r\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\r\n return Promise.resolve();\r\n }\r\n\r\n private onLog(entry: LogEntry): void {\r\n this.push({ kind: \"log\", ...entry });\r\n }\r\n\r\n private onJob(evt: JobEvent): void {\r\n this.push({ kind: \"job\", ...evt });\r\n }\r\n\r\n private onNotify(msg: NotifyEvent): void {\r\n this.push({ ...msg,kind: \"ui\", });\r\n }\r\n\r\n private push(obj: object): void {\r\n this.buffer.push(JSON.stringify(obj));\r\n if (!this.timer) {\r\n this.timer = setTimeout(() => void this.flush(), 1000);\r\n }\r\n if (this.buffer.length > 200) void this.flush();\r\n }\r\n\r\n private async flush(): Promise<void> {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n if (this.buffer.length === 0) return;\r\n\r\n // await fs.mkdir(path.dirname(this.filePath), { recursive: true });\r\n // const lines = this.buffer.splice(0).join(\"\\n\") + \"\\n\";\r\n // await fs.appendFile(this.filePath, lines, \"utf8\");\r\n }\r\n}\r\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { NotifyScope } from \"../core/types.js\";\n\nexport class OSSignalOrchestrator implements Orchestrator {\n public readonly name = \"os-signals-orchestrator\";\n\n private sigint?: () => void;\n private sigterm?: () => void;\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n const handler = (sig: string) => {\n ctx.notifier.warn(`received ${sig}`, { scope: NotifyScope.System });\n ctx.engine.requestStop(sig);\n };\n\n // Store bound handlers so we can remove them later\n this.sigint = () => handler(\"SIGINT\");\n this.sigterm = () => handler(\"SIGTERM\");\n\n process.on(\"SIGINT\", this.sigint);\n process.on(\"SIGTERM\", this.sigterm);\n }\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\n return Promise.resolve();\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n if (this.sigint){\n process.off(\"SIGINT\", this.sigint);\n }\n if (this.sigterm){\n process.off(\"SIGTERM\", this.sigterm);\n }\n this.sigint = undefined;\n this.sigterm = undefined;\n\n ctx.notifier.info(\"OS signal handlers removed\", { scope: NotifyScope.System });\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n return Promise.resolve();\n }\n}\n", "import React from 'react';\nimport { render } from 'ink';\nimport { Engine } from '../core/engine.js';\nimport { EventBus } from '../core/eventBus.js';\nimport { EngineEventMap } from '../core/events.js';\nimport App from './app.js';\n\nexport function renderUi(engine: Engine, bus: EventBus<EngineEventMap>) {\n const { waitUntilExit } = render(React.createElement(App, { engine, bus }));\n return waitUntilExit();\n}\n", "import React, { useEffect, useCallback } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { useStdoutDimensions } from './hooks/useStdoutDimensions.js';\nimport StatusBar from './components/StatusBar.js';\nimport LogPane from './components/LogPane.js';\nimport InputBar from './components/InputBar.js';\nimport ErrorBoundary from './components/ErrorBoundary.js';\nimport { EventBus } from '../core/eventBus.js';\nimport type { EngineEventMap } from '../core/events.js';\nimport { NotifyEvent } from '../core/events.js';\nimport { Engine } from '../core/engine.js';\nimport { NotifyKind, NotifyScope } from '../core/types.js';\nimport { AppContextProvider, useAppContext } from './context/AppContext.js';\n\ninterface AppProps {\n engine: Engine;\n bus: EventBus<EngineEventMap>;\n}\n\nfunction AppContent() {\n const { exit } = useApp();\n const { state, dispatch, engine, bus } = useAppContext();\n const [columns, rows] = useStdoutDimensions();\n const width = columns;\n const height = rows;\n\n // Create command handler\n const commandHandler = useCallback(\n (command: string) => bus.emit(\"console:command\", command),\n [bus]\n );\n\n // Calculate responsive layout\n // Reserve space for: StatusBar (1-2 lines), padding (2), InputBar (1), and some margin\n const availableHeight = Math.max(5, height - 5);\n const logPaneHeight = Math.min(availableHeight - 3, Math.max(5, Math.floor(availableHeight * 0.7)));\n\n // Handle Ctrl+C for graceful exit and arrow keys for history navigation\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n engine.requestStop('user exit');\n return;\n }\n\n // Handle arrow keys for command history (only when not processing)\n if (!state.isProcessing && (key.upArrow || key.downArrow)) {\n if (state.commandHistory.length === 0) return;\n\n if (key.upArrow) {\n const newIndex = state.historyIndex === -1 ? state.commandHistory.length - 1 : Math.max(0, state.historyIndex - 1);\n dispatch({ type: 'SET_HISTORY_INDEX', payload: newIndex });\n dispatch({ type: 'SET_INPUT', payload: state.commandHistory[newIndex]! });\n } else if (key.downArrow) {\n if (state.historyIndex === -1) return;\n const newIndex = state.historyIndex + 1;\n if (newIndex >= state.commandHistory.length) {\n dispatch({ type: 'SET_HISTORY_INDEX', payload: -1 });\n dispatch({ type: 'SET_INPUT', payload: '' });\n } else {\n dispatch({ type: 'SET_HISTORY_INDEX', payload: newIndex });\n dispatch({ type: 'SET_INPUT', payload: state.commandHistory[newIndex]! });\n }\n }\n }\n });\n\n // Reset history index when user manually types - handled in reducer\n useEffect(() => {\n dispatch({ type: 'RESET_HISTORY_INDEX_IF_TYPING' });\n }, [state.input, dispatch]);\n\n const onSubmit = useCallback(\n async (line: string) => {\n const trimmed = line.trim();\n dispatch({ type: 'RESET_INPUT' });\n dispatch({ type: 'RESET_HISTORY_INDEX' });\n\n // Add to history if not empty and not duplicate of last command\n if (trimmed) {\n dispatch({ type: 'ADD_COMMAND_TO_HISTORY', payload: trimmed });\n }\n\n dispatch({ type: 'SET_IS_PROCESSING', payload: true });\n try {\n await commandHandler(trimmed);\n } catch (e: any) {\n const errorMessage = e?.message ?? String(e);\n const errorMsg = new NotifyEvent(`Command failed: ${errorMessage}`, { ts: Date.now(), kind: NotifyKind.Error });\n dispatch({ type: 'ADD_MESSAGE', payload: errorMsg });\n } finally {\n dispatch({ type: 'SET_IS_PROCESSING', payload: false });\n }\n },\n [dispatch, exit, commandHandler, engine]\n );\n\n const handleError = useCallback(\n (error: Error, errorInfo: React.ErrorInfo) => {\n const errorMsg = new NotifyEvent(`UI Error: ${error.message}`, { ts: Date.now(), kind: NotifyKind.Error });\n dispatch({ type: 'ADD_MESSAGE', payload: errorMsg });\n },\n [dispatch]\n );\n\n return (\n <ErrorBoundary onError={handleError}>\n <Box flexDirection=\"column\" padding={1} width={width}>\n <StatusBar width={width - 2} />\n <Box height={1} />\n <LogPane height={logPaneHeight} width={width - 2} />\n <Box height={1} />\n <InputBar width={width - 2} onSubmit={onSubmit} />\n </Box>\n </ErrorBoundary>\n );\n}\n\nexport default function App({ engine, bus }: AppProps) {\n return (\n <AppContextProvider engine={engine} bus={bus}>\n <AppContent />\n </AppContextProvider>\n );\n}\n", "import { useEffect, useState } from 'react';\n\n/**\n * Hook to get terminal dimensions (columns and rows)\n * Updates on terminal resize events\n */\nexport function useStdoutDimensions(): [number, number] {\n const [dimensions, setDimensions] = useState<[number, number]>(() => {\n // Get initial dimensions\n const columns = process.stdout.columns || 80;\n const rows = process.stdout.rows || 24;\n return [columns, rows];\n });\n\n useEffect(() => {\n // Update dimensions on resize\n const updateDimensions = () => {\n const columns = process.stdout.columns || 80;\n const rows = process.stdout.rows || 24;\n setDimensions([columns, rows]);\n };\n\n // Listen for resize events\n process.stdout.on('resize', updateDimensions);\n\n // Get initial dimensions\n updateDimensions();\n\n return () => {\n process.stdout.off('resize', updateDimensions);\n };\n }, []);\n\n return dimensions;\n}\n", "import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { useAppContext } from '../context/AppContext.js';\n\n// Simplified state for now - will be enhanced when bridge integration is complete\ntype EngineState = 'IDLE' | 'RUNNING' | 'STOPPING' | 'STOPPED';\n\nfunction stateColor(s: EngineState): string {\n if (s === 'RUNNING') return 'green';\n if (s === 'STOPPING') return 'yellow';\n if (s === 'STOPPED') return 'red';\n return 'gray';\n}\n\nfunction connectionStatusColor(status: 'disconnected' | 'connecting' | 'connected'): string {\n if (status === 'connected') return 'green';\n if (status === 'connecting') return 'yellow';\n return 'red';\n}\n\nfunction connectionStatusText(status: 'disconnected' | 'connecting' | 'connected'): string {\n if (status === 'connected') return 'connected';\n if (status === 'connecting') return 'trying';\n return 'disconnected';\n}\n\nfunction truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return text.slice(0, Math.max(0, maxLength - 3)) + '...';\n}\n\nfunction StatusBar(props: { width: number }) {\n const { state } = useAppContext();\n const title = 'DeviceLink Agent';\n const debugEnabled = state.debugEnabled;\n const deviceId = state.deviceId ?? 'not signed in';\n const engineState = state.engineState;\n const stateColorValue = stateColor(engineState);\n const isProcessing = state.isProcessing;\n const connectionStatus = state.connectionStatus;\n const connectionRetryInSec = state.connectionRetryInSec;\n const refreshCountdownSec = state.refreshCountdownSec;\n\n // Real-time countdown for refresh\n const [currentRefreshCountdown, setCurrentRefreshCountdown] = useState<number | null>(refreshCountdownSec);\n const [currentRetryCountdown, setCurrentRetryCountdown] = useState<number | null>(connectionRetryInSec);\n\n // Sync with state changes\n useEffect(() => {\n setCurrentRefreshCountdown(refreshCountdownSec);\n }, [refreshCountdownSec]);\n\n useEffect(() => {\n setCurrentRetryCountdown(connectionRetryInSec);\n }, [connectionRetryInSec]);\n\n // Countdown timer for refresh\n useEffect(() => {\n if (refreshCountdownSec === null || refreshCountdownSec <= 0) {\n setCurrentRefreshCountdown(null);\n return;\n }\n \n setCurrentRefreshCountdown(refreshCountdownSec);\n \n const interval = setInterval(() => {\n setCurrentRefreshCountdown((prev) => {\n if (prev === null || prev <= 1) return null;\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [refreshCountdownSec]);\n\n // Countdown timer for retry\n useEffect(() => {\n if (connectionRetryInSec === null || connectionRetryInSec <= 0) {\n setCurrentRetryCountdown(null);\n return;\n }\n \n setCurrentRetryCountdown(connectionRetryInSec);\n \n const interval = setInterval(() => {\n setCurrentRetryCountdown((prev) => {\n if (prev === null || prev <= 1) return null;\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [connectionRetryInSec]);\n\n // Connection status\n const connStatusText = connectionStatusText(connectionStatus);\n const connStatusColor = connectionStatusColor(connectionStatus);\n\n // Calculate available width for right side\n const titleWidth = title.length;\n const minRightWidth = 30; // Minimum space needed\n const availableWidth = props.width - titleWidth - 2; // 2 for spacing\n\n // Build status display parts\n const statusElements: React.ReactNode[] = [];\n \n // Connection status\n statusElements.push(\n <Text key=\"conn\" color={connStatusColor}>{connStatusText}</Text>\n );\n \n // Retry countdown\n if (currentRetryCountdown !== null && currentRetryCountdown > 0) {\n statusElements.push(\n <Text key=\"retry\" color={connStatusColor}>retry in {currentRetryCountdown}s</Text>\n );\n }\n \n // Refresh countdown (only show when under 5 seconds)\n if (currentRefreshCountdown !== null && currentRefreshCountdown > 0 && currentRefreshCountdown <= 5) {\n statusElements.push(\n <Text key=\"refresh\" color=\"cyan\">refresh in {currentRefreshCountdown}s</Text>\n );\n }\n\n // If we have enough space, show horizontal layout\n if (availableWidth >= minRightWidth) {\n const deviceIdDisplay = truncate(deviceId, Math.max(5, availableWidth - 50));\n return (\n <Box justifyContent=\"space-between\" width={props.width}>\n <Box>\n <Text bold>{title}</Text>\n {debugEnabled && (\n <>\n <Text> </Text>\n <Text color=\"yellow\" bold>[DEBUG]</Text>\n </>\n )}\n </Box>\n <Box>\n {isProcessing && (\n <>\n <Text dimColor>\u23F3 </Text>\n </>\n )}\n <Text dimColor>device </Text>\n <Text>{deviceIdDisplay} </Text>\n <Text>\u00B7 </Text>\n <Text color={stateColorValue}>{engineState}</Text>\n {statusElements.length > 0 && (\n <>\n <Text> \u00B7 </Text>\n {statusElements.map((el, idx) => (\n <React.Fragment key={idx}>\n {idx > 0 && <Text> \u00B7 </Text>}\n {el}\n </React.Fragment>\n ))}\n </>\n )}\n </Box>\n </Box>\n );\n }\n\n // Otherwise, stack vertically\n const deviceIdDisplay = truncate(deviceId, props.width - 8);\n return (\n <Box flexDirection=\"column\" width={props.width}>\n <Box>\n <Text bold>{title}</Text>\n {debugEnabled && (\n <>\n <Text> </Text>\n <Text color=\"yellow\" bold>[DEBUG]</Text>\n </>\n )}\n </Box>\n <Box>\n {isProcessing && (\n <>\n <Text dimColor>\u23F3 </Text>\n </>\n )}\n <Text dimColor>device </Text>\n <Text>{deviceIdDisplay} </Text>\n <Text>\u00B7 </Text>\n <Text color={stateColorValue}>{engineState}</Text>\n {statusElements.length > 0 && (\n <>\n <Text> \u00B7 </Text>\n {statusElements.map((el, idx) => (\n <React.Fragment key={idx}>\n {idx > 0 && <Text> \u00B7 </Text>}\n {el}\n </React.Fragment>\n ))}\n </>\n )}\n </Box>\n </Box>\n );\n}\n\nexport default StatusBar;\nexport type { EngineState };\n", "import React, { createContext, useContext, useReducer, useMemo, useEffect, useState, ReactNode } from 'react';\nimport { EventBus } from '../../core/eventBus.js';\nimport { NotifyEvent } from '../../core/events.js';\nimport { Engine, EngineRuntime } from '../../core/engine.js';\nimport { EnginePhase, NotifyKind, NotifyScope } from '../../core/types.js';\nimport type { EngineState } from '../components/StatusBar.js';\nimport type { EngineEventMap } from '../../core/events.js';\n\n// State interface\ninterface AppState {\n input: string;\n messages: NotifyEvent[];\n engineState: EngineState;\n commandHistory: string[];\n historyIndex: number;\n isProcessing: boolean;\n debugEnabled: boolean;\n connectionStatus: 'disconnected' | 'connecting' | 'connected';\n connectionRetryInSec: number | null;\n refreshCountdownSec: number | null;\n deviceId: string | null;\n}\n\n// Action types\ntype AppAction =\n | { type: 'SET_INPUT'; payload: string }\n | { type: 'ADD_MESSAGE'; payload: NotifyEvent }\n | { type: 'SET_MESSAGES'; payload: NotifyEvent[] }\n | { type: 'SET_ENGINE_STATE'; payload: EngineState }\n | { type: 'ADD_COMMAND_TO_HISTORY'; payload: string }\n | { type: 'SET_HISTORY_INDEX'; payload: number }\n | { type: 'SET_IS_PROCESSING'; payload: boolean }\n | { type: 'SET_DEBUG_ENABLED'; payload: boolean }\n | { type: 'SET_CONNECTION_STATUS'; payload: 'disconnected' | 'connecting' | 'connected' }\n | { type: 'SET_CONNECTION_RETRY'; payload: number | null }\n | { type: 'SET_REFRESH_COUNTDOWN'; payload: number | null }\n | { type: 'SET_DEVICE_ID'; payload: string | null }\n | { type: 'RESET_INPUT' }\n | { type: 'RESET_HISTORY_INDEX' }\n | { type: 'RESET_HISTORY_INDEX_IF_TYPING' };\n\n// Context interface\ninterface AppContextValue {\n // State\n state: AppState;\n dispatch: React.Dispatch<AppAction>;\n \n // Readonly engine context\n readonly engine: Engine;\n readonly bus: EventBus<EngineEventMap>;\n readonly runtime: Readonly<EngineRuntime>;\n}\n\n// Create context\nconst AppContext = createContext<AppContextValue | null>(null);\n\nfunction messageUpsert(state: AppState, incoming: NotifyEvent): AppState {\n const messages = state.messages;\n\n // 1) Replace by id (rare in your setup, but keep it)\n const byId = messages.findIndex(m => m.id === incoming.id);\n if (byId !== -1) {\n const existing = messages[byId];\n const next = [...messages];\n // \u2705 preserve position/identity\n next[byId] = {\n ...incoming,\n id: existing.id,\n ts: existing.ts,\n } as NotifyEvent;\n return { ...state, messages: next };\n }\n\n // 2) Replace latest message in same group (your countdown case)\n if (incoming.groupKey) {\n for (let i = messages.length - 1; i >= 0; i--) {\n const existing = messages[i];\n if (existing.groupKey === incoming.groupKey) {\n const next = [...messages];\n // \u2705 preserve index + react key + sort position\n next[i] = {\n ...incoming,\n id: existing.id,\n ts: existing.ts,\n groupKey: existing.groupKey,\n } as NotifyEvent;\n return { ...state, messages: next };\n }\n }\n }\n\n // 3) Otherwise append\n return { ...state, messages: [...messages.slice(-380), incoming] };\n}\n\n\n// Reducer\nfunction appReducer(state: AppState, action: AppAction): AppState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, input: action.payload };\n \n case 'ADD_MESSAGE':\n return messageUpsert(state, action.payload);\n \n case 'SET_MESSAGES':\n return { ...state, messages: action.payload };\n \n case 'SET_ENGINE_STATE':\n return { ...state, engineState: action.payload };\n \n case 'ADD_COMMAND_TO_HISTORY':\n if (!action.payload) return state;\n const newHistory = state.commandHistory.length === 0 || state.commandHistory[state.commandHistory.length - 1] !== action.payload\n ? [...state.commandHistory, action.payload]\n : state.commandHistory;\n return { ...state, commandHistory: newHistory };\n \n case 'SET_HISTORY_INDEX':\n return { ...state, historyIndex: action.payload };\n \n case 'SET_IS_PROCESSING':\n return { ...state, isProcessing: action.payload };\n \n case 'SET_DEBUG_ENABLED':\n return { ...state, debugEnabled: action.payload };\n \n case 'SET_CONNECTION_STATUS':\n return { ...state, connectionStatus: action.payload };\n \n case 'SET_CONNECTION_RETRY':\n return { ...state, connectionRetryInSec: action.payload };\n \n case 'SET_REFRESH_COUNTDOWN':\n return { ...state, refreshCountdownSec: action.payload };\n \n case 'SET_DEVICE_ID':\n return { ...state, deviceId: action.payload };\n \n case 'RESET_INPUT':\n return { ...state, input: '' };\n \n case 'RESET_HISTORY_INDEX':\n return { ...state, historyIndex: -1 };\n \n case 'RESET_HISTORY_INDEX_IF_TYPING':\n // Reset history index if user is typing something different from current history item\n if (state.historyIndex !== -1) {\n const historyItem = state.commandHistory[state.historyIndex];\n if (historyItem !== undefined && state.input !== historyItem) {\n return { ...state, historyIndex: -1 };\n }\n }\n return state;\n \n default:\n return state;\n }\n}\n\n// Initial state\nconst initialState: AppState = {\n input: '',\n messages: [],\n engineState: 'IDLE',\n commandHistory: [],\n historyIndex: -1,\n isProcessing: false,\n debugEnabled: false,\n connectionStatus: 'disconnected',\n connectionRetryInSec: null,\n refreshCountdownSec: null,\n deviceId: null,\n};\n\n// Provider props\ninterface AppContextProviderProps {\n engine: Engine;\n bus: EventBus<EngineEventMap>;\n children: ReactNode;\n}\n\n// Provider component\nexport function AppContextProvider({ engine, bus, children }: AppContextProviderProps) {\n const [state, dispatch] = useReducer(appReducer, initialState);\n\n // Get readonly runtime reference - updates when engine runtime changes\n const [runtime, setRuntime] = useState<Readonly<EngineRuntime>>(() => {\n return Object.freeze({\n phase: engine.runtime.phase,\n flags: Object.freeze({\n debug: engine.runtime.flags.debug,\n }),\n }) as Readonly<EngineRuntime>;\n });\n\n useEffect(() => {\n bus.emit(\"ui:initialized\", Date.now());\n }, [bus]);\n\n // Single consolidated useEffect for all subscriptions and polling\n useEffect(() => {\n const phaseToState = (phase: string): EngineState => {\n if (phase === EnginePhase.Running) return 'RUNNING';\n if (phase === EnginePhase.Stopping) return 'STOPPING';\n if (phase === EnginePhase.Booting) return 'IDLE';\n return 'STOPPED';\n };\n\n const uiSub = bus.on('notify:event', (msg: NotifyEvent) => {\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\n \n // Parse refresh countdown from auth refresh messages\n if (msg.groupKey?.startsWith('auth:refresh')) {\n if (msg.kind === NotifyKind.Info) {\n const match = msg.message.match(/refresh scheduled in (\\d+)s/);\n if (match) {\n const seconds = parseInt(match[1]!, 10);\n if (!isNaN(seconds)) {\n dispatch({ type: 'SET_REFRESH_COUNTDOWN', payload: seconds });\n }\n }\n } else if (msg.kind === NotifyKind.Success && msg.message.includes('refresh completed')) {\n // Clear countdown when refresh completes\n dispatch({ type: 'SET_REFRESH_COUNTDOWN', payload: null });\n }\n }\n });\n\n const updateRuntime = () => {\n const rt = engine.runtime;\n\n dispatch({ type: 'SET_ENGINE_STATE', payload: phaseToState(rt.phase) });\n dispatch({ type: 'SET_DEBUG_ENABLED', payload: rt.flags.debug });\n\n const deviceId = engine.configurationContext.configuration.device?.id ?? null;\n dispatch({ type: 'SET_DEVICE_ID', payload: deviceId });\n\n setRuntime(\n Object.freeze({\n phase: rt.phase,\n flags: Object.freeze({ debug: rt.flags.debug }),\n }) as Readonly<EngineRuntime>\n );\n };\n updateRuntime();\n\n // Listen for engine phase changes via events\n const startedSub = bus.on('engine:started', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'RUNNING' });\n updateRuntime();\n });\n\n const stoppingSub = bus.on('engine:stopping', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'STOPPING' });\n updateRuntime();\n });\n\n const stoppedSub = bus.on('engine:stopped', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'STOPPED' });\n updateRuntime();\n });\n\n // Listen for WebSocket connection events\n const wsConnectingSub = bus.on('ws:connecting', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connecting' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsConnectedSub = bus.on('ws:connected', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connected' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsDisconnectedSub = bus.on('ws:disconnected', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'disconnected' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsRetryingSub = bus.on('ws:retrying', (payload: { retryInSec: number }) => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connecting' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: payload.retryInSec });\n });\n\n const debugSub = bus.on(\"runtime:debug:changed\", ({ enabled }) => {\n dispatch({ type: \"SET_DEBUG_ENABLED\", payload: enabled });\n\n const rt = engine.runtime;\n setRuntime(\n Object.freeze({\n phase: rt.phase,\n flags: Object.freeze({ debug: enabled }),\n }) as Readonly<EngineRuntime>\n );\n });\n\n const configLoadedSub = bus.on(\"config:loaded\", (cfg) => {\n const deviceId = cfg.device?.id ?? null;\n dispatch({ type: \"SET_DEVICE_ID\", payload: deviceId });\n });\n\n // Initial welcome messages (only once)\n const welcomeMsg = new NotifyEvent('Welcome to DeviceLink Agent UI', { ts: Date.now(), kind: NotifyKind.Status });\n const helpMsg = new NotifyEvent('Type \"help\" for commands. Start bridge with: start or run', { ts: Date.now(), kind: NotifyKind.Status });\n dispatch({ type: 'SET_MESSAGES', payload: [welcomeMsg, helpMsg] });\n\n return () => {\n uiSub.unsubscribe();\n startedSub.unsubscribe();\n stoppingSub.unsubscribe();\n stoppedSub.unsubscribe();\n wsConnectingSub.unsubscribe();\n wsConnectedSub.unsubscribe();\n wsDisconnectedSub.unsubscribe();\n wsRetryingSub.unsubscribe();\n debugSub.unsubscribe();\n configLoadedSub.unsubscribe();\n };\n }, [bus, engine, dispatch]);\n\n // Context value\n const value = useMemo<AppContextValue>(\n () => ({\n state,\n dispatch,\n engine,\n bus,\n runtime,\n }),\n [state, engine, bus, runtime]\n );\n\n return <AppContext.Provider value={value}>{children}</AppContext.Provider>;\n}\n\n// Hook to use the context\nexport function useAppContext(): AppContextValue {\n const context = useContext(AppContext);\n if (!context) {\n throw new Error('useAppContext must be used within AppContextProvider');\n }\n return context;\n}\n\n// Custom hook for messages in different formats\nexport interface UseMessagesReturn {\n /** Raw, unfiltered messages */\n rawMessages: NotifyEvent[];\n \n /** Messages filtered for display (e.g., excludes refresh scheduled messages) */\n messagesToDisplay: NotifyEvent[];\n \n /** Get messages filtered by a custom predicate */\n getFilteredMessages: (predicate: (msg: NotifyEvent) => boolean) => NotifyEvent[];\n \n /** Get messages by kind */\n getMessagesByKind: (kind: NotifyKind) => NotifyEvent[];\n \n /** Get messages by scope */\n getMessagesByScope: (scope: NotifyScope) => NotifyEvent[];\n}\n\n/**\n * Custom hook that provides messages in different formats\n * \n * @example\n * ```tsx\n * // Basic usage - get filtered messages for display\n * const { messagesToDisplay } = useMessages();\n * \n * // Get raw unfiltered messages\n * const { rawMessages } = useMessages();\n * \n * // Custom filter\n * const { messagesToDisplay } = useMessages({\n * displayFilter: (msg) => msg.kind !== NotifyKind.Debug\n * });\n * \n * // Get messages by kind\n * const { getMessagesByKind } = useMessages();\n * const errors = getMessagesByKind(NotifyKind.Error);\n * ```\n * \n * @param options Configuration options for message filtering\n */\nexport function useMessages(options?: {\n /** Filter function to apply to messagesToDisplay (default: filters refresh scheduled messages) */\n displayFilter?: (msg: NotifyEvent) => boolean;\n}): UseMessagesReturn {\n const { state } = useAppContext();\n \n // Default filter: exclude auth refresh scheduled messages and token-refresh category (they're shown in status bar)\n const defaultDisplayFilter = (msg: NotifyEvent): boolean => {\n // Skip messages with token-refresh category\n if (msg.category?.includes('token-refresh')) {\n return false;\n }\n // Skip messages that match the refresh scheduled pattern\n if (msg.groupKey?.startsWith('auth:refresh') && msg.kind === NotifyKind.Info) {\n if (msg.message.includes('refresh scheduled in')) {\n return false;\n }\n }\n return true;\n };\n \n const displayFilter = options?.displayFilter ?? defaultDisplayFilter;\n \n // Memoize filtered messages\n const messagesToDisplay = useMemo(() => {\n return state.messages.filter(displayFilter);\n }, [state.messages, displayFilter]);\n \n // Helper functions\n const getFilteredMessages = useMemo(() => {\n return (predicate: (msg: NotifyEvent) => boolean) => {\n return state.messages.filter(predicate);\n };\n }, [state.messages]);\n \n const getMessagesByKind = useMemo(() => {\n return (kind: NotifyKind) => {\n return state.messages.filter(msg => msg.kind === kind);\n };\n }, [state.messages]);\n \n const getMessagesByScope = useMemo(() => {\n return (scope: NotifyScope) => {\n return state.messages.filter(msg => msg.scope === scope);\n };\n }, [state.messages]);\n \n return useMemo(() => ({\n rawMessages: state.messages,\n messagesToDisplay,\n getFilteredMessages,\n getMessagesByKind,\n getMessagesByScope,\n }), [state.messages, messagesToDisplay, getFilteredMessages, getMessagesByKind, getMessagesByScope]);\n}\n", "import React, { useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport { useMessages } from '../context/AppContext.js';\nimport { NotifyKind } from '../../core/types.js';\nimport { NotifyEvent } from '../../core/events.js';\n\nfunction kindColor(k: NotifyKind): string {\n if (k === NotifyKind.Error) return 'red';\n if (k === NotifyKind.Warning) return 'yellow';\n if (k === NotifyKind.Success) return 'green';\n if (k === NotifyKind.Info) return 'cyan';\n return 'white';\n}\n\nfunction kindTag(k: NotifyKind): string {\n if (k === NotifyKind.Error) return 'ERROR';\n if (k === NotifyKind.Warning) return 'WARN';\n if (k === NotifyKind.Success) return 'SUCCESS';\n if (k === NotifyKind.Info) return 'INFO';\n if (k === NotifyKind.Status) return 'STATUS';\n return 'INFO';\n}\n\nfunction formatTime(ts: number): string {\n const d = new Date(ts);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n}\n\nfunction wrapText(text: string, maxWidth: number): string[] {\n if (typeof text !== 'string') {\n text = String(text ?? '');\n }\n if (text.length <= maxWidth) return [text];\n const lines: string[] = [];\n let currentLine = '';\n const words = text.split(/(\\s+)/);\n for (const word of words) {\n if ((currentLine + word).length <= maxWidth) {\n currentLine += word;\n } else {\n if (currentLine) lines.push(currentLine);\n currentLine = '';\n let remainingWord = word;\n while (remainingWord.length > maxWidth) {\n lines.push(remainingWord.slice(0, maxWidth));\n remainingWord = remainingWord.slice(maxWidth);\n }\n currentLine = remainingWord;\n }\n }\n if (currentLine) lines.push(currentLine);\n return lines.length > 0 ? lines : [text];\n}\n\nconst LogPane = React.memo(\n function LogPane(props: { height?: number; width: number }) {\n const { messagesToDisplay } = useMessages();\n const h = props.height ?? 14;\n\n const timestampWidth = 9; // \"HH:MM:SS \"\n const kindTagWidth = 8; // \"INFO \" or \"ERROR \"\n const padding = 2;\n const border = 2;\n const availableWidth = Math.max(\n 20,\n props.width - timestampWidth - kindTagWidth - padding - border,\n );\n\n const view = useMemo(() => {\n return messagesToDisplay.slice(-h);\n }, [messagesToDisplay, h]);\n\n const wrappedMessages = useMemo(() => {\n return view.flatMap((msg) => {\n const timeStr = formatTime(msg.ts);\n const kindStr = kindTag(msg.kind);\n const wrapped = wrapText(msg.message, availableWidth);\n return wrapped.map((line, lineIndex) => ({\n msg,\n lineIndex,\n time: lineIndex === 0 ? timeStr : '',\n kind: lineIndex === 0 ? kindStr : '',\n message: line,\n isContinuation: lineIndex > 0,\n }));\n });\n }, [view, availableWidth]);\n\n const displayMessages = wrappedMessages.slice(-h);\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n height={h + 2}\n width={props.width}\n >\n {displayMessages.length === 0 ? (\n <Text dimColor>(no messages)</Text>\n ) : (\n displayMessages.map((item) => (\n <LogRow key={`${item.msg.id}:${item.lineIndex}`} item={item} />\n ))\n )}\n </Box>\n );\n },\n (prevProps, nextProps) => prevProps.height === nextProps.height && prevProps.width === nextProps.width,\n);\n\nconst LogRow = React.memo(function LogRow({\n item,\n}: {\n item: {\n time: string;\n kind: string;\n message: string;\n isContinuation: boolean;\n msg: NotifyEvent;\n lineIndex: number;\n };\n}) {\n return (\n <Text>\n {item.time && <Text dimColor>{item.time} </Text>}\n {item.kind && <Text color={kindColor(item.msg.kind)}>{item.kind}</Text>}\n {item.kind && <Text> </Text>}\n {item.isContinuation && <Text dimColor> </Text>}\n <Text>{item.message}</Text>\n </Text>\n );\n});\n\nexport default LogPane;\n", "import React from 'react';\nimport { Box, Text, useFocus } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useAppContext } from '../context/AppContext.js';\n\nconst InputBar = React.memo(function InputBar(props: {\n onSubmit: (v: string) => void;\n width: number;\n isPassphraseMode?: boolean;\n passphraseError?: string;\n}) {\n const { state, dispatch } = useAppContext();\n const { isFocused } = useFocus({ autoFocus: true, isActive: !state.isProcessing });\n\n\n const prompt = props.isPassphraseMode ? 'passphrase> ' : 'dlink> ';\n const maxInputWidth = Math.max(10, props.width - prompt.length - 2);\n\n return (\n <Box flexDirection=\"column\" width={props.width}>\n <Box width={props.width}>\n <Text color={props.isPassphraseMode ? 'cyan' : 'green'}>{prompt}</Text>\n <Box width={maxInputWidth}>\n {state.isProcessing ? (\n <Text dimColor italic>\n Processing...\n </Text>\n ) : (\n <TextInput\n key={`input-${state.historyIndex}-${props.isPassphraseMode ? 'passphrase' : 'normal'}`}\n value={state.input}\n onChange={(value) => dispatch({ type: 'SET_INPUT', payload: value })}\n onSubmit={props.onSubmit}\n placeholder={isFocused ? undefined : props.isPassphraseMode ? 'Enter passphrase...' : 'Type a command or \"help\"'}\n mask={props.isPassphraseMode ? '*' : undefined}\n />\n )}\n </Box>\n </Box>\n {props.passphraseError && (\n <Box marginTop={1}>\n <Text color=\"red\">{props.passphraseError}</Text>\n </Box>\n )}\n </Box>\n );\n});\n\nexport default InputBar;\n", "import React, { Component, type ReactNode } from 'react';\nimport { Box, Text } from 'ink';\n\ninterface Props {\n children: ReactNode;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\nexport default class ErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n if (this.props.onError) {\n this.props.onError(error, errorInfo);\n }\n }\n\n render() {\n if (this.state.hasError && this.state.error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box borderStyle=\"round\" borderColor=\"red\" paddingX={1}>\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n \u26A0\uFE0F Application Error\n </Text>\n <Box height={1} />\n <Text color=\"red\">{this.state.error.message}</Text>\n {this.state.error.stack && (\n <>\n <Box height={1} />\n <Text dimColor>{this.state.error.stack}</Text>\n </>\n )}\n <Box height={1} />\n <Text dimColor>Press Ctrl+C to exit</Text>\n </Box>\n </Box>\n </Box>\n );\n }\n\n return this.props.children;\n }\n}\n", "/**\n * Command parser with callback registry\n * Parses argv to extract commands and routes them to registered handlers\n */\n\nexport interface ParsedCommand {\n command: string;\n subcommand?: string;\n args: string[];\n options: Record<string, string | boolean>;\n}\n\nexport type CommandHandler = (parsed: ParsedCommand) => Promise<void> | void;\n\nexport class CommandParser {\n private readonly handlers: Map<string, CommandHandler> = new Map();\n private readonly subcommandHandlers: Map<string, Map<string, CommandHandler>> = new Map();\n\n /**\n * Register a command handler\n * @param command - Command name (e.g., 'signin', 'status')\n * @param handler - Callback function to execute\n */\n public command(command: string, handler: CommandHandler): this {\n if (this.handlers.has(command)) {\n throw new Error(`Command '${command}' is already registered`);\n }\n this.handlers.set(command, handler);\n return this;\n }\n\n /**\n * Register a subcommand handler\n * @param command - Parent command name (e.g., 'roots')\n * @param subcommand - Subcommand name (e.g., 'add', 'list')\n * @param handler - Callback function to execute\n */\n public subcommand(command: string, subcommand: string, handler: CommandHandler): this {\n if (!this.subcommandHandlers.has(command)) {\n this.subcommandHandlers.set(command, new Map());\n }\n const subcommands = this.subcommandHandlers.get(command)!;\n if (subcommands.has(subcommand)) {\n throw new Error(`Subcommand '${command} ${subcommand}' is already registered`);\n }\n subcommands.set(subcommand, handler);\n return this;\n }\n\n /**\n * Convert a command string to argv array format\n * @param command - Command string to tokenize\n * @returns argv array in process.argv format\n */\n private commandStringToArgv(command: string): string[] {\n // Simulate process.argv format: ['node', 'script', ...args]\n // The parser expects to skip the first two, so we add dummy entries\n const tokens: string[] = [];\n let current = '';\n let inQuotes = false;\n let quoteChar = '';\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]!;\n \n if (char === '\"' || char === \"'\") {\n if (inQuotes && char === quoteChar) {\n // Closing quote - push current token (even if empty for \"\")\n tokens.push(current);\n current = '';\n inQuotes = false;\n quoteChar = '';\n } else if (!inQuotes) {\n // Opening quote - save any current token first\n if (current) {\n tokens.push(current);\n current = '';\n }\n inQuotes = true;\n quoteChar = char;\n } else {\n // Different quote type inside quotes - treat as literal\n current += char;\n }\n } else if (char === ' ' && !inQuotes) {\n if (current) {\n tokens.push(current);\n current = '';\n }\n // Skip spaces outside quotes\n } else {\n current += char;\n }\n }\n \n // Push remaining token (or empty string if we ended in quotes)\n if (inQuotes || current) {\n tokens.push(current);\n }\n \n return ['node', 'script', ...tokens];\n }\n\n /**\n * Parse a command string and extract command information\n * @param commandString - Command string to parse\n * @returns Parsed command or null if no command found\n */\n public parseString(commandString: string): ParsedCommand | null {\n const argv = this.commandStringToArgv(commandString);\n return this.parse(argv);\n }\n\n /**\n * Parse argv and extract command information\n * @param argv - Process argv array\n * @returns Parsed command or null if no command found\n */\n public parse(argv: string[]): ParsedCommand | null {\n // Skip first two args (node executable and script path)\n const args = argv.slice(2);\n if (args.length === 0) {\n return null;\n }\n\n const result: ParsedCommand = {\n command: '',\n args: [],\n options: {},\n };\n\n let i = 0;\n \n // Extract command name (first non-flag argument)\n while (i < args.length && args[i]?.startsWith('--')) {\n i++;\n }\n \n if (i >= args.length || !args[i]) {\n return null;\n }\n\n result.command = args[i]!;\n i++;\n\n // Check for subcommand (next non-flag argument)\n while (i < args.length && args[i]?.startsWith('--')) {\n i++;\n }\n\n if (i < args.length && args[i] && !args[i]!.startsWith('--')) {\n result.subcommand = args[i]!;\n i++;\n }\n\n // Parse remaining arguments and options\n while (i < args.length) {\n const arg = args[i]!;\n \n if (arg.startsWith('--')) {\n // Option flag\n const optionName = arg.slice(2);\n \n // Check for --flag=value format\n if (optionName.includes('=')) {\n const [key, value] = optionName.split('=', 2);\n result.options[key] = value || true;\n } else {\n // Check if next arg is a value (not a flag)\n const nextArg = args[i + 1];\n if (nextArg && !nextArg.startsWith('--')) {\n result.options[optionName] = nextArg;\n i++; // Skip the value\n } else {\n // Boolean flag\n result.options[optionName] = true;\n }\n }\n } else {\n // Positional argument\n result.args.push(arg);\n }\n \n i++;\n }\n\n return result;\n }\n\n /**\n * Parse and execute command from argv\n * @param argv - Process argv array\n * @returns true if a command was found and executed, false otherwise\n */\n public async execute(argv: string[]): Promise<boolean> {\n const parsed = this.parse(argv);\n if (!parsed) {\n return false;\n }\n\n // Try subcommand first\n if (parsed.subcommand) {\n const subcommands = this.subcommandHandlers.get(parsed.command);\n if (subcommands) {\n const handler = subcommands.get(parsed.subcommand);\n if (handler) {\n await handler(parsed);\n return true;\n }\n }\n }\n\n // Try main command\n const handler = this.handlers.get(parsed.command);\n if (handler) {\n await handler(parsed);\n return true;\n }\n\n return false;\n }\n\n /**\n * Check if a command exists in the registry\n */\n public hasCommand(command: string, subcommand?: string): boolean {\n if (subcommand) {\n const subcommands = this.subcommandHandlers.get(command);\n return subcommands?.has(subcommand) ?? false;\n }\n return this.handlers.has(command);\n }\n\n /**\n * Get all registered command names\n */\n public getCommands(): string[] {\n return Array.from(this.handlers.keys());\n }\n}\n", "import { ParsedCommand } from \"./command.parser\";\nimport { JobType } from \"../core/job\";\n\nexport enum ConsoleCommandKind {\n Start = \"start\",\n Stop = \"stop\",\n SignIn = \"signin\",\n SignOut = \"signout\",\n Status = \"status\",\n RootsAdd = \"roots-add\",\n RootsList = \"roots-list\",\n Run = \"run\",\n Doctor = \"doctor\",\n DebugOn = \"debug-on\",\n DebugOff = \"debug-off\",\n }\n\nexport class ConsoleCommandInput {\n public readonly kind: ConsoleCommandKind;\n public readonly payloadJson: string | null;\n \n public constructor(kind: ConsoleCommandKind, payloadJson: string | null) {\n this.kind = kind;\n this.payloadJson = payloadJson;\n }\n }\n\n \n/**\n * Result of a pattern match\n */\nexport interface CommandMatchResult {\n handled: boolean;\n kind?: ConsoleCommandKind;\n job?: ConsoleCommandInput;\n }\n\n/**\n * Pattern matcher function type\n */\nexport type CommandMatcher = (params: string[], parsed: ParsedCommand) => CommandMatchResult;\n\n/**\n * Dispatchable job containing handler and input\n */\nexport interface DispatchableJob<TIn> {\n handler: JobType<TIn, unknown>;\n input: TIn;\n}\n\n/**\n * Command job builder using pattern matching\n */\nexport class CommandJobBuilder {\n private readonly matchers: CommandMatcher[] = [];\n /**\n * Register a pattern matcher function\n * @param matcher - Function that takes command params and parsed command, returns match result\n * @returns this for chaining\n */\n public register(matcher: CommandMatcher): this {\n this.matchers.push(matcher);\n return this;\n }\n \n /**\n * Build a dispatchable job from a parsed command\n * @param parsed - The parsed command\n * @returns DispatchableJob or null if no match found\n */\n public build(parsed: ParsedCommand): ConsoleCommandInput | null {\n // Build params array from command and subcommand\n const params: string[] = [parsed.command];\n if (parsed.subcommand) {\n params.push(parsed.subcommand);\n }\n \n // Try each matcher in order, stop at first match\n for (const matcher of this.matchers) {\n const result = matcher(params, parsed);\n if (result.handled) {\n // If job is provided, use it; otherwise create from kind\n let input: ConsoleCommandInput;\n if (result.job) {\n input = result.job;\n } else if (result.kind) {\n input = this.createCommandInput(result.kind, parsed);\n } else {\n // If handled but no job/kind, return null (handled but invalid)\n return null;\n }\n \n return input;\n }\n }\n \n return null;\n }\n \n /**\n * Create a ConsoleCommandInput from kind and parsed command\n */\n private createCommandInput(kind: ConsoleCommandKind, parsed: ParsedCommand): ConsoleCommandInput {\n const payload = {\n command: parsed.command,\n subcommand: parsed.subcommand,\n args: parsed.args,\n options: parsed.options,\n };\n return new ConsoleCommandInput(kind, JSON.stringify(payload));\n }\n }\n \n ", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { NotifyScope, DispatchStatus, NotifyKind } from \"../core/types.js\";\nimport { renderUi } from \"../ui/index.js\";\nimport { CommandParser } from \"../utils/command.parser.js\";\nimport { ConsoleCommandKind, CommandJobBuilder } from \"../utils/command-job.builder.js\";\nimport { consoleCommandCall } from \"../jobs/consoleCommand.js\";\n\n\nexport class ConsoleCommandOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ConsoleOrchestrator implements Orchestrator {\n public readonly name = \"console-orchestrator\";\n public readonly commandParser: CommandParser;\n public readonly commandJobBuilder: CommandJobBuilder;\n\n public constructor() {\n this.commandParser = new CommandParser();\n this.commandJobBuilder = new CommandJobBuilder();\n \n // Register all command mappings\n this.setupCommandMappings();\n }\n public onRegister(_ctx: OrchestratorContext): void {\n // Nothing to do on register\n }\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"Starting console orchestrator (UI)\", { scope: NotifyScope.System });\n \n ctx.on(\"console:command\", async (event) => {\n try {\n // Parse the command string\n const parsed = this.commandParser.parseString(event);\n \n if (!parsed) {\n ctx.notifier.warn(\"Invalid command format\");\n return;\n }\n \n // Build the command job\n const input = this.commandJobBuilder.build(parsed);\n \n if (!input) {\n ctx.notifier.warn(`Unknown command: ${parsed.command}${parsed.subcommand ? ' ' + parsed.subcommand : ''}`);\n return;\n }\n\n switch (input.kind) {\n case ConsoleCommandKind.SignIn:\n ctx.bus.emit(\"auth:signin:requested\", void 0);\n ctx.notifier.info(\"Sign-in requested\");\n break;\n\n case ConsoleCommandKind.SignOut:\n ctx.bus.emit(\"auth:signout:requested\", void 0);\n ctx.notifier.info(\"Sign-out requested\");\n break;\n\n case ConsoleCommandKind.DebugOn:\n ctx.flags.debug = true;\n ctx.bus.emit(\"runtime:debug:changed\", { enabled: true });\n ctx.notifier.success(\"Debug mode enabled\");\n break;\n\n case ConsoleCommandKind.DebugOff:\n ctx.flags.debug = false;\n ctx.bus.emit(\"runtime:debug:changed\", { enabled: false });\n ctx.notifier.success(\"Debug mode disabled\");\n break;\n\n default:\n ctx.notifier.warn(`Command not implemented: ${input.kind}`);\n break;\n }\n\n // // Dispatch the command\n // const call = consoleCommandCall(input);\n // const result = await ctx.engine.dispatch(call);\n // if (result.status !== DispatchStatus.Success) {\n // throw new Error(`Command '${input.kind}' failed: ${result.error ?? 'Unknown error'}`);\n // }\n \n // // Emit success message\n // ctx.notifier.success(`Command '${parsed.command}${parsed.subcommand ? ' ' + parsed.subcommand : ''}' executed`);\n } catch (error: any) {\n const errorMessage = error?.message ?? String(error);\n ctx.notifier.error(`Command failed: ${errorMessage}`);\n ctx.notifier.error(`Command execution error: ${errorMessage}`);\n }\n });\n\n }\n\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"Console orchestrator started\", { scope: NotifyScope.System });\n renderUi(ctx.engine, ctx.bus);\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"UI exited, stopping engine\", { scope: NotifyScope.System });\n if (ctx.engine) {\n ctx.engine.requestStop('UI exited');\n }\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n // Nothing to do\n }\n\n \n\n /**\n * Setup all command mappings using pattern matching\n */\n private setupCommandMappings(): void {\n const builder = this.commandJobBuilder;\n\n // Single command patterns\n builder.register((params) => {\n if (params.length === 1) {\n const cmd = params[0];\n if (cmd === 'start' || cmd === 'run') {\n return { handled: true, kind: ConsoleCommandKind.Start };\n }\n if (cmd === 'stop') {\n return { handled: true, kind: ConsoleCommandKind.Stop };\n }\n if (cmd === 'signin') {\n return { handled: true, kind: ConsoleCommandKind.SignIn };\n }\n if (cmd === 'signout') {\n return { handled: true, kind: ConsoleCommandKind.SignOut };\n }\n if (cmd === 'status') {\n return { handled: true, kind: ConsoleCommandKind.Status };\n }\n if (cmd === 'doctor') {\n return { handled: true, kind: ConsoleCommandKind.Doctor };\n }\n }\n return { handled: false };\n });\n\n // Subcommand patterns\n builder.register((params) => {\n if (params.length === 2) {\n const [cmd, subcmd] = params;\n if (cmd === 'roots') {\n if (subcmd === 'add') {\n return { handled: true, kind: ConsoleCommandKind.RootsAdd };\n }\n if (subcmd === 'list') {\n return { handled: true, kind: ConsoleCommandKind.RootsList };\n }\n }\n if (cmd === 'debug') {\n if (subcmd === 'on') {\n return { handled: true, kind: ConsoleCommandKind.DebugOn };\n }\n if (subcmd === 'off') {\n return { handled: true, kind: ConsoleCommandKind.DebugOff };\n }\n }\n }\n return { handled: false };\n });\n\n // Handle debug on/off as args (backward compatibility)\n builder.register((params, parsed) => {\n if (params.length === 1 && params[0] === 'debug' && parsed.args.length > 0) {\n const arg = parsed.args[0];\n if (arg === 'on') {\n return { handled: true, kind: ConsoleCommandKind.DebugOn };\n }\n if (arg === 'off') {\n return { handled: true, kind: ConsoleCommandKind.DebugOff };\n }\n }\n return { handled: false };\n });\n }\n\n}\n", "import WebSocket from \"ws\";\nimport * as Common from \"@devicelink-workspace/common\";\n\nexport type SocketState =\n | { kind: \"DISCONNECTED\" }\n | { kind: \"CONNECTING\" }\n | { kind: \"CONNECTED\" }\n | { kind: \"RETRYING\"; retryInSec: number }; // kept for compatibility (not used internally)\n\ntype SendItem = {\n data: WebSocket.Data;\n cb?: (err?: Error) => void;\n expiresAt: number;\n};\n\nexport class RecoverableSocket {\n private ws: WebSocket | null = null;\n private state: SocketState = { kind: \"DISCONNECTED\" };\n\n private stopped = false;\n private connecting = false;\n\n /** Increases each connection attempt; used to ignore events from old sockets */\n private connId = 0;\n\n /** Connection timeout */\n private connectionTimeout: NodeJS.Timeout | null = null;\n\n /** Heartbeat */\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private heartbeatTimeout: NodeJS.Timeout | null = null;\n private awaitingPong = false;\n\n /** Send queue */\n private sendQueue: SendItem[] = [];\n\n private readonly url: string;\n private readonly abortSignal?: AbortSignal;\n\n private readonly connectionTimeoutMs: number;\n private readonly heartbeatIntervalMs: number;\n private readonly pongTimeoutMs: number;\n\n private readonly maxSendQueueSize: number;\n private readonly sendQueueItemTtlMs: number;\n\n // Single callbacks\n private onStateChangeCallback?: (state: SocketState) => void;\n private onErrorCallback?: (error: Error) => void;\n private onConnectedCallback?: (ws: WebSocket) => void;\n private onDisconnectedCallback?: (code: number, reason: string) => void;\n private onMessageCallback?: (data: WebSocket.Data) => void;\n\n constructor(\n url: string,\n options: {\n abortSignal?: AbortSignal;\n /** How long to wait for TCP/TLS+WS handshake */\n connectionTimeoutMs?: number; // default 10s\n /** Heartbeat ping interval */\n heartbeatIntervalMs?: number; // default 20s\n /** How long to wait for a pong after ping */\n pongTimeoutMs?: number; // default 10s\n /** Queue outgoing sends while disconnected */\n maxSendQueueSize?: number; // default 1000\n sendQueueItemTtlMs?: number; // default 60s\n } = {}\n ) {\n this.url = url;\n this.abortSignal = options.abortSignal;\n\n this.connectionTimeoutMs = options.connectionTimeoutMs ?? 10_000;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? 20_000;\n this.pongTimeoutMs = options.pongTimeoutMs ?? 10_000;\n\n this.maxSendQueueSize = options.maxSendQueueSize ?? 1000;\n this.sendQueueItemTtlMs = options.sendQueueItemTtlMs ?? 60_000;\n\n if (this.abortSignal) {\n this.abortSignal.addEventListener(\n \"abort\",\n () => {\n this.stop();\n },\n { once: true }\n );\n }\n }\n\n // --- Public API ------------------------------------------------------------\n\n public registerOnStateChangeCallback(handler: (state: SocketState) => void): void {\n this.onStateChangeCallback = handler;\n }\n public registerOnErrorCallback(handler: (error: Error) => void): void {\n this.onErrorCallback = handler;\n }\n public registerOnConnectedCallback(handler: (ws: WebSocket) => void): void {\n this.onConnectedCallback = handler;\n }\n public registerOnDisconnectedCallback(handler: (code: number, reason: string) => void): void {\n this.onDisconnectedCallback = handler;\n }\n public registerOnMessageCallback(handler: (data: WebSocket.Data) => void): void {\n this.onMessageCallback = handler;\n }\n\n public getState(): SocketState {\n return this.state;\n }\n\n public getSocket(): WebSocket | null {\n return this.ws;\n }\n\n public isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Single connection attempt (NO internal retry). */\n public async connect(): Promise<void> {\n if (this.stopped) throw new Error(\"Socket is stopped\");\n if (this.connecting || this.isConnected()) return;\n\n this.connecting = true;\n this.updateState({ kind: \"CONNECTING\" });\n\n try {\n await this.connectWebSocketOnce();\n } catch (e: any) {\n const err = e instanceof Error ? e : new Error(String(e));\n this.onErrorCallback?.(err);\n this.updateState({ kind: \"DISCONNECTED\" });\n throw err;\n } finally {\n this.connecting = false;\n }\n }\n\n /** Permanently stop + disconnect. */\n public stop(): void {\n this.stopped = true;\n this.disconnect(true);\n }\n\n /** Disconnect current socket (graceful close, then terminate fallback). */\n public disconnect(permanent = false): void {\n if (permanent) this.stopped = true;\n\n // Cancel connect timeout\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = null;\n }\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n const ws = this.ws;\n this.ws = null;\n this.connecting = false;\n\n if (ws) {\n // IMPORTANT: close handshake first so server sees a real code (not 1005)\n this.closeGracefullyThenTerminate(ws, 1000, \"client disconnect\", 2000);\n }\n\n this.updateState({ kind: \"DISCONNECTED\" });\n }\n\n /**\n * Send data.\n * - If connected: sends immediately.\n * - If disconnected: queues until reconnected (up to limits).\n */\n public send(data: WebSocket.Data, cb?: (err?: Error) => void): void {\n if (this.stopped) {\n cb?.(new Error(\"Socket is stopped\"));\n return;\n }\n\n const ws = this.ws;\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(data, (err) => cb?.(err ?? undefined));\n return;\n }\n\n // Queue while offline\n const now = Date.now();\n this.pruneSendQueue(now);\n\n if (this.sendQueue.length >= this.maxSendQueueSize) {\n cb?.(new Error(`Send queue full (max ${this.maxSendQueueSize})`));\n return;\n }\n\n this.sendQueue.push({\n data,\n cb,\n expiresAt: now + this.sendQueueItemTtlMs,\n });\n }\n\n // --- Internals ------------------------------------------------------------\n\n /**\n * The key fix for \"1005\": never hard-kill immediately when we can close properly.\n * We send a close frame, then if it doesn't close soon, we terminate as a fallback.\n */\n private closeGracefullyThenTerminate(\n ws: WebSocket,\n code: number,\n reason: string,\n timeoutMs: number\n ) {\n try {\n if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {\n ws.close(code, reason);\n }\n } catch {\n // ignore\n }\n\n const t = setTimeout(() => {\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n }, timeoutMs);\n\n ws.once(\"close\", () => clearTimeout(t));\n }\n\n private async connectWebSocketOnce(): Promise<void> {\n const myConnId = ++this.connId;\n\n return new Promise((resolve, reject) => {\n if (this.stopped) {\n reject(new Error(\"Socket is stopped\"));\n return;\n }\n\n let opened = false;\n let settled = false;\n\n const cleanup = () => {\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = null;\n }\n };\n\n const settleResolve = () => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve();\n };\n\n const settleReject = (error: Error, ws?: WebSocket) => {\n if (settled) return;\n settled = true;\n cleanup();\n\n // If we created a socket, try close handshake first, terminate later.\n if (ws) {\n const code = opened ? 1011 : 1006; // 1006 isn't sent on wire; just local intent\n this.closeGracefullyThenTerminate(ws, 1000, \"connect failed\", 1500);\n }\n\n reject(error);\n };\n\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.url);\n\n // Connection timeout\n this.connectionTimeout = setTimeout(() => {\n settleReject(\n new Error(\n `Connection timeout: unable to connect to ${this.url} within ${this.connectionTimeoutMs}ms`\n ),\n ws\n );\n }, this.connectionTimeoutMs);\n\n ws.on(\"open\", () => {\n opened = true;\n\n if (myConnId !== this.connId) {\n // Old attempt opened late \u2014 close it gracefully\n this.closeGracefullyThenTerminate(ws, 1000, \"stale connection\", 500);\n return;\n }\n\n this.ws = ws;\n this.retryResetOnConnect();\n\n this.updateState({ kind: \"CONNECTED\" });\n this.onConnectedCallback?.(ws);\n\n // Heartbeat & queue flush\n this.startHeartbeat(myConnId);\n this.flushSendQueue();\n\n settleResolve();\n });\n\n ws.on(\"error\", (error) => {\n if (myConnId !== this.connId) return;\n\n const err = error instanceof Error ? error : new Error(String(error));\n\n // If not connected yet, fail the attempt\n if (!opened && !settled) {\n settleReject(err, ws);\n return;\n }\n\n // If already open, surface error; close will follow in many cases\n this.onErrorCallback?.(err);\n });\n\n ws.on(\"close\", (code, reason) => {\n if (myConnId !== this.connId) return;\n\n const reasonStr = reason?.toString?.() || \"\";\n\n // If close happens before open & before settleResolve, treat as connect failure\n if (!opened && !settled) {\n this.ws = null;\n this.stopHeartbeat();\n this.updateState({ kind: \"DISCONNECTED\" });\n settleReject(new Error(`WebSocket closed before connection established: ${code} ${reasonStr}`), ws);\n return;\n }\n\n // Normal disconnect after being connected\n if (this.ws === ws) this.ws = null;\n\n this.stopHeartbeat();\n this.updateState({ kind: \"DISCONNECTED\" });\n this.onDisconnectedCallback?.(code, reasonStr || `code ${code}`);\n });\n\n ws.on(\"message\", (data) => {\n if (myConnId !== this.connId) {\n this.onErrorCallback?.(new Error('Message ignored - connection ID mismatch'));\n return;\n }\n if (this.ws !== ws) {\n this.onErrorCallback?.(new Error('Message ignored - socket mismatch'));\n return;\n }\n this.onMessageCallback?.(data);\n });\n\n // Heartbeat pong handler\n ws.on(\"pong\", () => {\n if (myConnId !== this.connId) return;\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n });\n\n // Abort signal\n if (this.abortSignal) {\n this.abortSignal.addEventListener(\n \"abort\",\n () => {\n if (myConnId !== this.connId) return;\n\n // Close handshake first; terminate later if needed\n this.closeGracefullyThenTerminate(ws, 1000, \"aborted\", 1000);\n\n if (!settled) {\n settleReject(new Error(\"Connection aborted\"), ws);\n }\n },\n { once: true }\n );\n }\n } catch (e: any) {\n const err = e instanceof Error ? e : new Error(String(e));\n reject(err);\n }\n });\n }\n\n private retryResetOnConnect() {\n // kept as a hook in case you later want it; no internal retry now\n }\n\n private startHeartbeat(myConnId: number): void {\n this.stopHeartbeat();\n\n const ws = this.ws;\n if (!ws) return;\n\n this.awaitingPong = false;\n\n this.heartbeatInterval = setInterval(() => {\n if (this.stopped) return;\n if (myConnId !== this.connId) return;\n\n const current = this.ws;\n if (!current || current.readyState !== WebSocket.OPEN) return;\n\n // If previous ping wasn't answered -> close handshake then terminate\n if (this.awaitingPong) {\n this.closeGracefullyThenTerminate(current, 4000, \"pong timeout\", 1000);\n return;\n }\n\n this.awaitingPong = true;\n\n try {\n current.ping();\n } catch {\n this.closeGracefullyThenTerminate(current, 1011, \"ping failed\", 1000);\n return;\n }\n\n if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = setTimeout(() => {\n if (myConnId !== this.connId) return;\n const cur = this.ws;\n if (!cur) return;\n this.closeGracefullyThenTerminate(cur, 4000, \"pong timeout\", 1000);\n }, this.pongTimeoutMs);\n }, this.heartbeatIntervalMs);\n }\n\n private stopHeartbeat(): void {\n this.awaitingPong = false;\n\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n }\n\n private flushSendQueue(): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n\n const now = Date.now();\n this.pruneSendQueue(now);\n\n const items = this.sendQueue;\n this.sendQueue = [];\n\n for (const item of items) {\n ws.send(item.data, (err) => item.cb?.(err ?? undefined));\n }\n }\n\n private pruneSendQueue(now: number): void {\n if (this.sendQueue.length === 0) return;\n\n const kept: SendItem[] = [];\n for (const item of this.sendQueue) {\n if (item.expiresAt >= now) kept.push(item);\n else item.cb?.(new Error(\"Send dropped: queued item expired\"));\n }\n this.sendQueue = kept;\n }\n\n private updateState(state: SocketState): void {\n this.state = state;\n this.onStateChangeCallback?.(state);\n }\n}\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { NotifyScope, NotifyKind } from \"../core/types.js\";\nimport { Configuration } from \"../core/configuration.js\";\nimport { RecoverableSocket, SocketState } from \"../utils/recoverable-socket.js\";\nimport { sleep } from \"@devicelink-workspace/common\";\n\ntype StartReason =\n | \"onStarted\"\n | \"config:cache:validated\"\n | \"auth:signin:completed\"\n | \"auth:ws:reconnect\"\n | \"socket:disconnected\";\n\nexport class WebSocketOrchestrator implements Orchestrator {\n public readonly name = \"websocket-orchestrator\";\n\n private socket: RecoverableSocket | null = null;\n private stopped = false;\n\n private connectLoopInFlight: Promise<void> | null = null;\n\n private retryAttempt = 0;\n private countdownTimer: NodeJS.Timeout | null = null;\n\n private lastUrl: string | null = null;\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"WS: orchestrator started\", { scope: NotifyScope.System });\n }\n\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\n const config = ctx.engine.configurationContext.configuration;\n if (await this.isConnectableToBridge(config, ctx)) {\n this.ensureStarted(ctx, \"onStarted\");\n }\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n this.stopped = true;\n this.clearCountdown();\n\n if (this.socket) {\n ctx.notifier.info(\"WS: stopping socket (onStop)\", { scope: NotifyScope.System });\n this.socket.stop();\n this.socket = null;\n }\n\n ctx.notifier.info(\"WS: orchestrator stopped\", { scope: NotifyScope.System });\n }\n\n public async onStopped(): Promise<void> {}\n\n public handlers() {\n const initSocket = async (reason: StartReason, ctx: OrchestratorContext) => {\n if (this.stopped) return;\n\n const config = ctx.engine.configurationContext.configuration;\n if (!(await this.isConnectableToBridge(config, ctx))) return;\n\n this.ensureStarted(ctx, reason);\n };\n\n return {\n \"config:cache:validated\": async (_: void, ctx: OrchestratorContext) =>\n initSocket(\"config:cache:validated\", ctx),\n\n \"auth:signin:completed\": async (_: void, ctx: OrchestratorContext) =>\n initSocket(\"auth:signin:completed\", ctx),\n\n \"auth:signout:requested\": async (_: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(\"WS: sign-out requested -> disconnecting\");\n this.stopped = true;\n this.clearCountdown();\n this.socket?.stop();\n this.socket = null;\n },\n\n \"ws:disconnect\": async (p: { reason?: string }, ctx: OrchestratorContext) => {\n ctx.notifier.info(\"WS: disconnect requested\", { scope: NotifyScope.System });\n this.stopped = true;\n this.clearCountdown();\n this.socket?.stop();\n this.socket = null;\n },\n\n \"auth:ws:reconnect\": async (_: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(\"WS: reconnect requested by auth\", { scope: NotifyScope.System });\n\n this.retryAttempt = 0;\n this.clearCountdown();\n\n // reconnect without permanent stop\n this.socket?.disconnect(false);\n\n this.ensureStarted(ctx, \"auth:ws:reconnect\");\n },\n\n // the only sender\n \"ws:tx\": async (p: { text: string }, ctx: OrchestratorContext) => {\n const ws = this.socket?.getSocket();\n if (!ws || ws.readyState !== 1) {\n ctx.notifier.info(\"WS: TX dropped (not connected)\", { scope: NotifyScope.System });\n return;\n }\n ws.send(p.text);\n },\n };\n }\n\n private ensureStarted(ctx: OrchestratorContext, reason: StartReason) {\n if (this.connectLoopInFlight) {\n ctx.notifier.info(`WS: connect loop already running (reason=${reason})`, { scope: NotifyScope.System });\n return;\n }\n\n this.connectLoopInFlight = this.startOrJoinConnectLoop(ctx, reason).finally(() => {\n this.connectLoopInFlight = null;\n });\n }\n\n private async startOrJoinConnectLoop(ctx: OrchestratorContext, reason: StartReason): Promise<void> {\n this.stopped = false;\n\n const config = ctx.engine.configurationContext.configuration;\n const isConnectable = await this.isConnectableToBridge(config, ctx);\n if (!isConnectable) return;\n\n const url = String(config.bridgeWsUrl);\n this.lastUrl = url;\n\n ctx.notifier.info(`WS: ensure connection (reason=${reason}) url=${url}`, { scope: NotifyScope.System });\n\n if (!this.socket) {\n this.socket = new RecoverableSocket(url, {\n abortSignal: ctx.signal,\n connectionTimeoutMs: 10_000,\n heartbeatIntervalMs: 20_000,\n pongTimeoutMs: 10_000,\n });\n\n this.socket.registerOnStateChangeCallback((state) => this.handleStateChange(state, ctx));\n\n this.socket.registerOnErrorCallback((error) => {\n ctx.notifier.error(`WS: transport error: ${error.message}`);\n });\n\n this.socket.registerOnConnectedCallback((_ws) => {\n this.retryAttempt = 0;\n this.clearCountdown();\n\n ctx.notifier.success(`WS: connected (${url})`);\n ctx.bus.emit(\"ws:connected\", { url, attempt: 0 } as any);\n });\n\n this.socket.registerOnDisconnectedCallback((code, reasonStr) => {\n ctx.notifier.warn(`WS: disconnected code=${code} reason=${reasonStr || \"-\"}`);\n ctx.bus.emit(\"ws:disconnected\", { code, reason: reasonStr });\n\n // Auth-related close: do not auto loop; Auth will refresh and request reconnect\n if (code === 4001) {\n ctx.notifier.info(\"WS: auth disconnect (4001) -> waiting for auth\", { scope: NotifyScope.System });\n return;\n }\n\n // otherwise keep reconnect loop\n this.ensureStarted(ctx, \"socket:disconnected\");\n });\n\n this.socket.registerOnMessageCallback((data) => {\n const text = typeof data === \"string\" ? data : data.toString(\"utf8\");\n ctx.bus.emit(\"ws:rx\", { text });\n });\n }\n\n while (!this.stopped) {\n try {\n const attemptNo = this.retryAttempt + 1;\n ctx.notifier.info(`WS: connecting attempt #${attemptNo} to ${url}`, { scope: NotifyScope.System, groupKey: 'ws:connecting' });\n\n ctx.bus.emit(\"ws:connecting\", { url, attempt: attemptNo });\n\n await this.socket.connect();\n return;\n } catch (e: any) {\n if (this.stopped) return;\n\n this.retryAttempt += 1;\n\n const delayMs = this.computeBackoffMs(this.retryAttempt);\n const seconds = Math.max(1, Math.ceil(delayMs / 1000));\n const errMsg = String(e?.message ?? e ?? \"unknown error\");\n\n ctx.notifier.warn(\n `WS: connect failed (attempt=${this.retryAttempt}) -> retry in ${seconds}s (${errMsg})`,\n { scope: NotifyScope.System, category: ['websocket-connect'], groupKey: 'ws:connect-retry' }\n );\n\n ctx.bus.emit(\"ws:retrying\", { retryInSec: seconds, attempt: this.retryAttempt } as any);\n this.startCountdown(seconds, ctx);\n\n await this.interruptibleSleep(delayMs);\n }\n }\n }\n\n private async isConnectableToBridge(config: Configuration, ctx: OrchestratorContext): Promise<boolean> {\n if (!config.device?.id) {\n ctx.notifier.error(\"WS: cannot connect: device.id missing\");\n return false;\n }\n if (!config.bridgeWsUrl) {\n ctx.notifier.error(\"WS: cannot connect: bridgeWsUrl missing\");\n return false;\n }\n if (!config.device?.keys?.public) {\n ctx.notifier.error(\"WS: cannot connect: device public key missing\");\n return false;\n }\n\n const refreshRes = await ctx.engine.secrets.get(\"refreshToken\");\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\n if (!hasRefresh) {\n ctx.notifier.warn(\"WS: not connecting (no tokens). Run signin.\");\n return false;\n }\n\n return true;\n }\n\n private handleStateChange(state: SocketState, ctx: OrchestratorContext): void {\n if (state.kind === \"CONNECTING\") ctx.notifier.info(`WS: state CONNECTING (url=${this.lastUrl})`, { scope: NotifyScope.System });\n if (state.kind === \"CONNECTED\") ctx.notifier.info(`WS: state CONNECTED (url=${this.lastUrl})`, { scope: NotifyScope.System });\n if (state.kind === \"DISCONNECTED\") ctx.notifier.info(`WS: state DISCONNECTED (url=${this.lastUrl})`, { scope: NotifyScope.System });\n }\n\n private computeBackoffMs(attempt: number): number {\n const base = Math.min(30_000, 1000 * Math.pow(2, Math.min(attempt - 1, 5)));\n const jitter = base * (0.2 * (Math.random() * 2 - 1));\n return Math.max(250, Math.floor(base + jitter));\n }\n\n private startCountdown(seconds: number, ctx: OrchestratorContext) {\n this.clearCountdown();\n\n let remaining = seconds;\n this.countdownTimer = setInterval(() => {\n remaining -= 1;\n if (remaining <= 0) {\n this.clearCountdown();\n return;\n }\n ctx.bus.emit(\"ws:retrying\", { retryInSec: remaining, attempt: this.retryAttempt } as any);\n }, 1000);\n }\n\n private clearCountdown() {\n if (this.countdownTimer) {\n clearInterval(this.countdownTimer);\n this.countdownTimer = null;\n }\n }\n\n private async interruptibleSleep(ms: number): Promise<void> {\n const step = 100;\n const start = Date.now();\n while (Date.now() - start < ms) {\n if (this.stopped) return;\n await sleep(step);\n }\n }\n}\n", "import fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport os from 'node:os';\r\nimport { Configuration } from '../core/configuration';\r\nimport defaultTo from 'lodash/defaultTo.js';\r\n\r\nexport class ConfigurationWriter {\r\n /**\r\n * Saves the configuration to the standard config file location.\r\n * Strips any secret fields so they are never persisted to disk.\r\n */\r\n public static save(config: Configuration): string {\r\n const configDir = this.getApplicationConfigFolder();\r\n const configPath = path.join(configDir, 'config.json');\r\n\r\n const safe = this.stripSecrets(config);\r\n fs.mkdirSync(configDir, { recursive: true });\r\n fs.writeFileSync(configPath, JSON.stringify(safe, null, 2), 'utf8');\r\n\r\n return configPath;\r\n }\r\n\r\n private static stripSecrets(config: Configuration): Configuration {\r\n const device = config.device\r\n ? {\r\n id: config.device.id,\r\n name: config.device.name,\r\n tag: config.device.tag,\r\n keys: { public: config.device.keys.public },\r\n }\r\n : undefined;\r\n const tokens = config.tokens\r\n ? { accessTokenExpSec: config.tokens.accessTokenExpSec }\r\n : undefined;\r\n return {\r\n ...config,\r\n device,\r\n tokens,\r\n };\r\n }\r\n\r\n /**\r\n * Gets the application config folder path\r\n * Uses the same logic as ConfigBuilder.getApplicationConfigFolder()\r\n */\r\n private static getApplicationConfigFolder(): string {\r\n const appData = defaultTo(\r\n process.env['APPDATA'],\r\n path.join(os.homedir(), 'AppData', 'Roaming')\r\n );\r\n return path.join(appData, 'DeviceLink');\r\n }\r\n}\r\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { EnginePhase, NotifyScope } from \"../core/types.js\";\nimport { loadConfigCall, LoadConfigInput, type LoadConfigJob } from \"../jobs/loadConfig.js\";\nimport { Configuration } from \"../core/configuration.js\";\nimport { ConfigurationWriter } from \"../utils/configuration.writer.js\";\n\nexport class MainOrchestrator implements Orchestrator {\n public readonly name = \"main-orchestrator\";\n\n constructor() {}\n\n private bootStarted = false;\n\n // --- persistence control (prevents disk spam during frequent refresh) ---\n private saveTimer: NodeJS.Timeout | null = null;\n private saveInFlight: Promise<void> | null = null;\n private latestConfigToSave: Configuration | null = null;\n\n // tune this: 250\u20131000ms is usually nice\n private readonly saveDebounceMs = 500;\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(_ctx: OrchestratorContext): Promise<void> {}\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {}\n\n public async onStop(_ctx: OrchestratorContext): Promise<void> {\n // try to flush pending save on shutdown\n await this.flushSaveOnStop().catch(() => {});\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {}\n\n public handlers() {\n return {\n \"ui:initialized\": async (_ts: number, ctx: OrchestratorContext) => {\n if (this.bootStarted) return;\n this.bootStarted = true;\n\n ctx.engine.setPhase(EnginePhase.Booting);\n ctx.notifier.info(\"Booting...\");\n\n ctx.engine.dispatch(loadConfigCall(new LoadConfigInput()));\n },\n\n /**\n * Centralized disk persistence.\n * Any orchestrator can emit this after calling ctx.engine.applyConfiguration(updated).\n */\n \"config:save:requested\": async (config: Configuration, ctx: OrchestratorContext) => {\n this.latestConfigToSave = config;\n\n // debounce frequent writes (e.g., token refresh)\n if (this.saveTimer){\n clearTimeout(this.saveTimer);\n }\n this.saveTimer = setTimeout(() => {\n void this.performSave(ctx);\n }, this.saveDebounceMs);\n },\n };\n }\n\n private async performSave(ctx: OrchestratorContext): Promise<void> {\n // if a save is already running, let it finish; it will re-check latestConfigToSave afterwards\n if (this.saveInFlight) return;\n\n this.saveInFlight = (async () => {\n while (this.latestConfigToSave) {\n const config = this.latestConfigToSave;\n this.latestConfigToSave = null;\n\n try {\n const configPath = ConfigurationWriter.save(config);\n\n ctx.notifier.info(`Config saved to: ${configPath}`, { scope: NotifyScope.System });\n\n // keep compatibility with your existing listeners\n ctx.bus.emit(\"config:saved\", void 0);\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n ctx.notifier.error(`Failed to save configuration: ${msg}`);\n\n // optional failure event if you want UIs to react\n // ctx.bus.emit(\"configuration:save:failed\", { message: msg });\n }\n }\n })().finally(() => {\n this.saveInFlight = null;\n });\n\n await this.saveInFlight;\n }\n\n private async flushSaveOnStop(): Promise<void> {\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n // cannot access ctx here (stop signature passes ctx but you aren\u2019t using it), so do a best-effort:\n // If you want guaranteed flush with notifier logs, pass ctx to onStop and call performSave(ctx).\n }\n}\n", "import { Orchestrator, OrchestratorContext } from '../core/orchestrator.js';\nimport { DispatchStatus, NotifyScope, NotifyKind, EnginePhase } from '../core/types.js';\nimport { decodeJwt } from 'jose';\nimport crypto from 'node:crypto';\nimport { Configuration } from '../core/configuration.js';\nimport { Api } from '../api/index.js';\nimport { fingerprintFromPublicKeyPem, signConnect } from '@devicelink-workspace/common';\nimport { BridgeOutboundMsgSchema } from '@devicelink-workspace/domain';\nimport type {\n DeviceAuthStartResponse,\n DeviceAuthStreamResponse,\n ConnectRequest,\n SessionInitRequest,\n ConnectAck,\n SessionInitAck,\n DisconnectNoticeResponse,\n SessionConflictRequest,\n SessionConflictResolveAck,\n DeviceAuthRefreshRequest,\n DeviceAuthRefreshResponse,\n ToolCallRequest,\n} from '@devicelink-workspace/domain';\nimport type { BaseStorage } from '../../storage/index.js';\nimport {\n refreshTokensCall,\n REFRESH_UNRECOVERABLE_CODES,\n RefreshTokensInput,\n RefreshTokensOutput,\n type RefreshTokensJob,\n} from '../jobs/refreshTokens.js';\nimport { Scheduler } from '../utils/scheduler.js';\n\ntype Phase = 'IDLE' | 'CONNECT_SENT' | 'WAIT_SESSION_INIT_ACK' | 'READY';\n\ntype TokenReason =\n | 'boot'\n | 'signin'\n | 'connect_ack_next'\n | 'ws_4001'\n | 'timer'\n | 'manual'\n | 'retry';\n\nexport class AuthOrchestrator implements Orchestrator {\n public readonly name = 'auth-orchestrator';\n\n private phase: Phase = 'IDLE';\n private connectionId: string | null = null;\n private sessionId: string | null = null;\n private accessToken?: string;\n\n private refreshGroupKey = 'auth:refresh';\n private refreshCycle = 0;\n private refreshScheduler: Scheduler | null = null;\n private refreshRetryScheduler: Scheduler | null = null;\n private lastRefreshPlan?: { exp: number | null; groupKey: string };\n\n private refreshInFlight?: Promise<boolean>;\n\n private conflictTimer: NodeJS.Timeout | null = null;\n private pendingConflictRequest: SessionConflictRequest | null = null;\n\n private signinStarted = false;\n\n public onRegister(): void {}\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info('Auth orchestrator started', { scope: NotifyScope.System });\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n this.clearTimers();\n this.resetConnectionState();\n ctx.notifier.info('Auth orchestrator stopped', { scope: NotifyScope.System });\n }\n\n public async onStarted(): Promise<void> {}\n public async onStopped(): Promise<void> {}\n\n public handlers() {\n return {\n 'config:loaded': this.onEventConfigLoaded.bind(this),\n 'config:cache:validated': this.onEventConfigCacheValidated.bind(this),\n\n 'auth:signin:requested': this.onEventAuthSigninRequested.bind(this),\n\n 'auth:signin:completed': async (_: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(\n 'Auth: signin completed; requesting ws reconnect',\n { scope: NotifyScope.System },\n );\n this.ensureAccessExpPersisted(ctx, 'signin');\n await this.ensureRefreshScheduling(ctx, 'signin');\n ctx.bus.emit('auth:ws:reconnect', void 0);\n },\n\n 'auth:signout:requested': async (_: void, ctx: OrchestratorContext) => {\n ctx.notifier.info('Signing out\u2026');\n\n // 1. Stop refresh scheduler\n this.clearTimers();\n\n // 2. Clear in-memory access token\n this.accessToken = undefined;\n\n // 3. Remove refresh token from secure storage (if exists)\n try {\n await ctx.engine.secrets.delete('refreshToken');\n } catch {\n // ignore if not present\n }\n\n // 4. Clear tokens from configuration\n const cfg = ctx.engine.configurationContext.configuration;\n const updated: Configuration = {\n ...cfg,\n tokens: undefined,\n };\n\n ctx.engine.applyConfiguration(updated);\n ctx.bus.emit('config:save:requested', updated);\n\n // 5. Reset connection state\n this.resetConnectionState();\n\n // 6. Reset engine phase to not-authenticated\n ctx.engine.setPhase(EnginePhase.Idle);\n\n // 7. Inform system that tokens changed (cleared)\n ctx.bus.emit('auth:tokens:updated', {\n accessToken: '',\n refreshToken: '',\n expSec: undefined,\n });\n\n // 8. Explicitly disconnect WebSocket\n ctx.bus.emit('ws:disconnect', { reason: 'signout' });\n\n // 9. Notify UI\n ctx.notifier.success('Signed out successfully');\n },\n\n 'auth:session_conflict:resolve': async (\n p: { choice: 'USE_NEW' | 'KEEP_OLD' },\n ctx: OrchestratorContext,\n ) => {\n this.sendSessionConflictResolve(ctx, p.choice);\n },\n\n 'ws:connected': async (_: unknown, ctx: OrchestratorContext) => {\n this.resetConnectionState();\n\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\n const hasAccess = !!this.accessToken;\n\n ctx.notifier.info(\n `Auth: ws connected; tokens access=${hasAccess} refresh=${hasRefresh}`,\n { scope: NotifyScope.System },\n );\n\n if (!hasAccess && !hasRefresh) {\n ctx.notifier.warn('Auth: no tokens; run signin');\n return;\n }\n\n await this.sendConnect(ctx);\n },\n\n 'ws:rx': async (p: { text: string }, ctx: OrchestratorContext) => {\n this.onInbound(p.text, ctx);\n },\n\n 'ws:disconnected': async (\n p: { code: number; reason?: string },\n ctx: OrchestratorContext,\n ) => {\n ctx.notifier.warn(\n `Auth: ws disconnected code=${p.code} reason=${p.reason ?? '-'}`,\n { scope: NotifyScope.System },\n );\n this.resetConnectionState();\n\n if (p.code === 4001) {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value) {\n ctx.notifier.warn(\n 'Auth: token invalid and no refresh; please sign in',\n );\n await this.teardownTokens(ctx, 'AUTH_REQUIRED');\n return;\n }\n\n const ok = await this.requestRefresh(ctx, {\n force: true,\n reason: 'ws_4001',\n });\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\n }\n },\n };\n }\n\n // --- boot path unchanged except it must schedule refresh always ---\n private async onEventConfigLoaded(\n config: Configuration,\n ctx: OrchestratorContext,\n ) {\n ctx.notifier.info(\n 'Initializing with cached configuration',\n );\n\n if (!config.device?.id) {\n ctx.notifier.error('Device ID is not available');\n return;\n }\n if (!config.device.keys?.public) {\n ctx.notifier.error(\n 'Device public key is not available',\n );\n return;\n }\n\n ctx.bus.emit('config:cache:validated', void 0);\n }\n\n private async onEventConfigCacheValidated(_: void, ctx: OrchestratorContext) {\n this.ensureAccessExpPersisted(ctx, 'boot');\n await this.ensureRefreshScheduling(ctx, 'boot');\n\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\n const hasAccess = !!this.accessToken;\n const accessOk = this.isAccessLikelyUsable(ctx);\n\n ctx.notifier.info(\n `Auth: cache validated; access=${hasAccess} refresh=${hasRefresh} accessOk=${accessOk}`,\n { scope: NotifyScope.System },\n );\n\n if (!hasAccess && !hasRefresh) {\n ctx.notifier.warn('Auth: not signed in; run signin');\n return;\n }\n\n ctx.bus.emit('auth:ws:reconnect', void 0);\n }\n\n private isAccessLikelyUsable(ctx: OrchestratorContext): boolean {\n const jwt = this.accessToken;\n if (!jwt) return false;\n const cfg = ctx.engine.configurationContext.configuration;\n const exp = cfg?.tokens?.accessTokenExpSec ?? this.tryDecodeExp(jwt);\n if (!exp) return true;\n const now = Math.floor(Date.now() / 1000);\n return exp > now;\n }\n\n // --- signin path unchanged (kept from your code) ---\n private async waitForApproval(\n api: Api,\n startResponse: DeviceAuthStartResponse,\n ctx: OrchestratorContext,\n ): Promise<DeviceAuthStreamResponse | null> {\n const deadline = Date.now() + startResponse.expires_in * 1000;\n ctx.notifier.info(\n 'Waiting for approval... (streaming)',\n );\n\n try {\n return await api.deviceAuthStream({\n deviceCode: startResponse.device_code,\n timeoutMs: Math.max(1000, deadline - Date.now()),\n signal: ctx.signal,\n });\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n ctx.notifier.error(\n `Failed to wait for approval: ${msg}`,\n );\n return null;\n }\n }\n\n private async onEventAuthSigninRequested(_: void, ctx: OrchestratorContext) {\n if (this.signinStarted) {\n ctx.notifier.warn('Sign-in already in progress', { scope: NotifyScope.System });\n return;\n }\n\n this.signinStarted = true;\n\n try {\n const configuration = ctx.engine.configurationContext.configuration;\n\n if (!configuration.controlBaseUrl) {\n ctx.notifier.error('Control base URL is not set');\n return;\n }\n if (!configuration.device?.id) {\n ctx.notifier.error('Device ID is not available');\n return;\n }\n if (!configuration.device.keys?.public) {\n ctx.notifier.error(\n 'Device public key is not available',\n );\n return;\n }\n\n const privateRes = await ctx.engine.secrets.get('devicePrivateKey');\n if (!privateRes.ok || !privateRes.value) {\n ctx.notifier.error(\n 'Device private key is not available (secret storage)',\n );\n return;\n }\n const privateKeyPem = privateRes.value;\n\n const deviceName = configuration.device.name as string;\n const platform = process.platform;\n const publicKeyPem = configuration.device.keys.public;\n\n const fingerprint = fingerprintFromPublicKeyPem(publicKeyPem);\n const api = new Api(configuration, ctx.notifier);\n\n ctx.notifier.info(\n 'Starting device authentication...',\n );\n\n const startResponse = await api.deviceAuthStart({\n device_id: configuration.device.id,\n device_name: deviceName,\n platform,\n public_key_pem: publicKeyPem,\n });\n\n ctx.notifier.info('DeviceLink sign-in');\n ctx.notifier.info(\n `User code: ${startResponse.user_code}`,\n );\n ctx.notifier.info(\n `Device fingerprint: ${fingerprint}`,\n );\n ctx.notifier.info(\n `Verification URL: ${startResponse.verification_uri_complete}`,\n );\n\n const streamResp = await this.waitForApproval(api, startResponse, ctx);\n if (!streamResp) return;\n\n if ('error' in streamResp) {\n if (streamResp.error === 'access_denied') {\n ctx.notifier.error('Sign-in denied in browser.');\n return;\n }\n if (streamResp.error === 'expired_token') {\n ctx.notifier.error(\n 'Sign-in expired. Run `signin` again.',\n );\n return;\n }\n ctx.notifier.error(\n `Unexpected error: ${(streamResp as { error: string }).error}`,\n );\n return;\n }\n\n if (streamResp.status !== 'approved') {\n ctx.notifier.error(\n `Unexpected status: ${streamResp.status}`,\n );\n return;\n }\n\n if (streamResp.needs_proof) {\n ctx.notifier.info(\n 'Sending proof-of-possession signature...',\n );\n\n const privKeyObj = crypto.createPrivateKey(privateKeyPem);\n const challengeBytes = Buffer.from(\n startResponse.challenge,\n 'base64url',\n );\n const sig = crypto.sign(null, challengeBytes, privKeyObj);\n const signatureB64 = sig.toString('base64');\n\n await api.deviceAuthProve({\n device_code: startResponse.device_code,\n challenge_id: startResponse.challenge_id,\n challenge: startResponse.challenge,\n signature_b64: signatureB64,\n });\n\n ctx.notifier.info('Proof-of-possession verified');\n }\n\n ctx.notifier.info('Fetching tokens...');\n\n const tokenResp = await api.deviceAuthToken({\n device_code: startResponse.device_code,\n });\n\n const deviceTag = 'tag'; // computeDeviceTag(...)\n\n await ctx.engine.secrets.set('refreshToken', tokenResp.refresh_token);\n this.accessToken = tokenResp.access_token;\n\n const expFromJwt = this.tryDecodeExp(tokenResp.access_token);\n const updatedConfig: Configuration = {\n ...configuration,\n controlBaseUrl: configuration.controlBaseUrl,\n device: {\n ...configuration.device,\n id: tokenResp.device_id,\n name: deviceName,\n tag: deviceTag,\n keys: {\n public: publicKeyPem,\n },\n },\n tokens: {\n ...(configuration.tokens ?? {}),\n accessTokenExpSec: expFromJwt ?? undefined,\n },\n };\n\n ctx.engine.applyConfiguration(updatedConfig);\n ctx.bus.emit('config:save:requested', updatedConfig);\n\n ctx.bus.emit('auth:signin:completed', void 0);\n\n ctx.notifier.success('Signed in successfully \u2705');\n } catch (e: any) {\n if (['ECONNREFUSED', 'ENOTFOUND', 'ETIMEDOUT'].includes(e?.code)) {\n ctx.notifier.error(\n `Network error: ${e?.message ?? String(e)}`,\n );\n return;\n }\n ctx.notifier.error(\n `Sign-in failed: ${e?.message ?? String(e)}`,\n );\n } finally {\n this.signinStarted = false;\n }\n }\n\n // ---------------------------\n // Outbound steps\n // ---------------------------\n\n // --- ws protocol steps ---\n private async sendConnect(ctx: OrchestratorContext): Promise<void> {\n const config = ctx.engine.configurationContext.configuration;\n const device = config.device;\n\n const privateRes = await ctx.engine.secrets.get('devicePrivateKey');\n if (!device?.id || !privateRes.ok || !privateRes.value) {\n ctx.notifier.warn(\n 'Cannot connect: device not configured',\n );\n return;\n }\n const privateKeyPem = privateRes.value;\n\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n const refreshToken = refreshRes.ok ? refreshRes.value : undefined;\n\n const ts = Date.now();\n const nonce = crypto.randomBytes(16).toString('base64url');\n const sig = signConnect({\n deviceId: device.id,\n ts,\n nonce,\n privateKeyPem,\n });\n\n const connectMessage: ConnectRequest = {\n type: 'connect',\n device_id: device.id,\n agent_version: String(config.version ?? '1'),\n ts,\n nonce,\n sig,\n platform: process.platform,\n hostname: device.name,\n device_tag: device.tag,\n access_token: this.accessToken,\n refresh_token: refreshToken,\n public_key_pem: device.keys.public,\n };\n\n this.phase = 'CONNECT_SENT';\n ctx.notifier.info('Auth: sending connect', { scope: NotifyScope.System });\n this.send(ctx, connectMessage);\n }\n\n private async sendSessionInit(\n ctx: OrchestratorContext,\n ack: ConnectAck,\n ): Promise<void> {\n const config = ctx.engine.configurationContext.configuration;\n const device = config.device;\n if (!device?.id || !this.sessionId) {\n ctx.notifier.error('Cannot send session_init: device ID or session ID not available');\n return;\n }\n\n const msg: SessionInitRequest = {\n type: 'session_init',\n device_id: device.id,\n session_id: this.sessionId,\n };\n\n this.phase = 'WAIT_SESSION_INIT_ACK';\n ctx.notifier.info('Auth: sending session_init', { scope: NotifyScope.System });\n this.send(ctx, msg);\n }\n\n // --- inbound handling ---\n private onInbound(text: string, ctx: OrchestratorContext): void {\n let obj: unknown;\n try {\n obj = JSON.parse(text);\n } catch (e: any) {\n ctx.notifier.error('Unexpected message format');\n return;\n }\n\n const parsed = BridgeOutboundMsgSchema.safeParse(obj);\n if (!parsed.success) {\n const message = parsed.error.message;\n ctx.notifier.error(`Unexpected message format: ${message}`);\n return;\n }\n\n const msg = parsed.data;\n\n switch (msg.type) {\n case 'connect_ack':\n ctx.bus.emit('auth:connect_ack', msg);\n void this.onConnectAck(ctx, msg);\n return;\n\n case 'session_init_ack':\n ctx.bus.emit('auth:session_init_ack', msg);\n this.onSessionInitAck(ctx, msg);\n return;\n\n case 'disconnect_notice':\n this.onDisconnectNotice(ctx, msg);\n return;\n\n case 'session_conflict':\n ctx.bus.emit('auth:session_conflict', msg);\n void this.handleSessionConflict(ctx, msg);\n return;\n\n default:\n return;\n }\n }\n\n async handleSessionConflict(\n ctx: OrchestratorContext,\n msg: SessionConflictRequest,\n ): Promise<void> {\n if (this.conflictTimer) {\n clearTimeout(this.conflictTimer);\n this.conflictTimer = null;\n }\n this.pendingConflictRequest = msg;\n\n const deadlineMs = Math.min(msg.deadline_ms, 15_000);\n this.conflictTimer = setTimeout(() => {\n this.conflictTimer = null;\n if (this.pendingConflictRequest?.new_session_id === msg.new_session_id) {\n this.sendSessionConflictResolve(ctx, 'KEEP_OLD');\n }\n }, deadlineMs);\n }\n\n sendSessionConflictResolve(\n ctx: OrchestratorContext,\n choice: 'USE_NEW' | 'KEEP_OLD',\n ): void {\n const req = this.pendingConflictRequest;\n if (!req) return;\n if (this.conflictTimer) {\n clearTimeout(this.conflictTimer);\n this.conflictTimer = null;\n }\n this.pendingConflictRequest = null;\n\n this.send(ctx, {\n type: 'session_conflict_resolve',\n device_id: req.device_id,\n new_session_id: req.new_session_id,\n choice,\n });\n }\n\n private async onConnectAck(\n ctx: OrchestratorContext,\n ack: ConnectAck,\n ): Promise<void> {\n if (!ack.ok) {\n ctx.notifier.error(\n `Connect rejected: ${ack.error.code} ${ack.error.message}`,\n );\n this.phase = 'IDLE';\n return;\n }\n\n this.sessionId = ack.session_id;\n\n const accessStatus = ack.auth.access_token;\n ctx.notifier.info(\n `Auth: connect_ack ok auth.access=${accessStatus} next=[${ack.next.join(',')}]`,\n { scope: NotifyScope.System },\n );\n\n // 1) honor server next\n if (ack.next.includes('refresh_access_token')) {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value) {\n ctx.notifier.warn(\n 'Auth: server requested refresh but no refresh token; please sign in',\n );\n await this.teardownTokens(ctx, 'NO_REFRESH_TOKEN');\n return;\n }\n\n const ok = await this.requestRefresh(ctx, {\n force: true,\n reason: 'connect_ack_next',\n });\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\n else\n ctx.notifier.warn(\n 'Auth: refresh failed; please sign in',\n );\n\n return;\n }\n\n if (ack.next.includes('session_init')) {\n await this.sendSessionInit(ctx, ack);\n return;\n }\n\n // 2) fallback\n if (accessStatus === 'invalid' || accessStatus === 'missing') {\n ctx.notifier.warn(\n 'Auth: access token invalid; please sign in again',\n );\n await this.teardownTokens(ctx, 'INVALID_ACCESS');\n return;\n }\n\n ctx.notifier.warn(\n 'Auth: connect_ack had no next; staying idle',\n { scope: NotifyScope.System },\n );\n }\n\n private onSessionInitAck(\n ctx: OrchestratorContext,\n ack: SessionInitAck,\n ): void {\n if (!ack.ok) {\n ctx.notifier.error(\n `Session init failed: ${ack.error.code} ${ack.error.message}`,\n );\n this.phase = 'IDLE';\n return;\n }\n\n this.sessionId = ack.session_id;\n this.phase = 'READY';\n\n ctx.notifier.success(`Session ready (${ack.mode})`);\n\n void this.ensureRefreshScheduling(ctx, 'manual');\n\n // Honor server's next array - emit events for meta-data orchestrator\n if (ack.next) {\n if (ack.next.includes('tools_publish')) {\n ctx.bus.emit('meta:data:requested:tools', void 0);\n }\n if (ack.next.includes('directories_publish')) {\n ctx.bus.emit('meta:data:requested:directories', void 0);\n }\n }\n }\n\n private onDisconnectNotice(\n ctx: OrchestratorContext,\n msg: DisconnectNoticeResponse,\n ) {\n ctx.notifier.warn(\n `Server disconnect_notice: ${msg.reason} (code=${msg.code})`,\n );\n }\n\n // --- refresh via job only ---\n private async requestRefresh(\n ctx: OrchestratorContext,\n opts: { force: boolean; reason: TokenReason },\n ): Promise<boolean> {\n if (this.refreshInFlight) return this.refreshInFlight;\n\n this.refreshInFlight = (async () => {\n try {\n return await this.withTimeout(\n this.dispatchRefreshJob(ctx, opts),\n 60_000,\n 'Refresh operation',\n );\n } catch (error) {\n if (error instanceof Error && error.message.includes('timed out')) {\n ctx.notifier.error(\n `Auth: refresh timed out: ${error.message}`,\n { category: ['token-refresh'], groupKey: 'auth:refresh-failure' },\n );\n }\n throw error;\n } finally {\n this.refreshInFlight = undefined;\n }\n })();\n\n return this.refreshInFlight;\n }\n\n private async withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n operation: string,\n ): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`${operation} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n ]);\n }\n\n private async dispatchRefreshJob(\n ctx: OrchestratorContext,\n opts: { force: boolean; reason: TokenReason },\n ): Promise<boolean> {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value) return false;\n\n if (!opts.force) {\n const check = await this.shouldRefreshNow(ctx);\n if (!check.ok) {\n ctx.notifier.info(\n `Auth: skip refresh (${check.reason})`,\n { scope: NotifyScope.System, category: ['token-refresh'] },\n );\n return false;\n }\n }\n\n ctx.notifier.info(\n `Auth: dispatch refresh job (${opts.reason})`,\n { scope: NotifyScope.System, category: ['token-refresh'] },\n );\n\n const call = refreshTokensCall(new RefreshTokensInput(opts.reason));\n const out = await ctx.engine.dispatch(call);\n\n ctx.notifier.info(\n `Auth: refresh job dispatch completed (status=${out.status})`,\n { scope: NotifyScope.System, category: ['token-refresh'] },\n );\n\n if (out.status !== DispatchStatus.Success) {\n const msg = out.error?.message ?? 'Unknown error';\n ctx.notifier.error(\n `Auth: refresh job failed: ${msg}`,\n { category: ['token-refresh'], groupKey: 'auth:refresh-failure' },\n );\n const output = out.output as RefreshTokensOutput | undefined;\n if (output?.errorCode && REFRESH_UNRECOVERABLE_CODES.includes(output.errorCode as typeof REFRESH_UNRECOVERABLE_CODES[number])) {\n await this.teardownTokens(ctx, output.errorCode);\n return false;\n }\n this.scheduleRefreshRetry(ctx, opts.reason, output?.retryAfterSec);\n return false;\n }\n\n const output: RefreshTokensOutput = out.output as RefreshTokensOutput;\n\n if (!output.ok || !output.accessToken) {\n const err = output.error ?? 'Unknown refresh failure';\n ctx.notifier.error(`Auth: refresh failed: ${err}`, { category: ['token-refresh'], groupKey: 'auth:refresh-failure' });\n if (output.errorCode && REFRESH_UNRECOVERABLE_CODES.includes(output.errorCode as typeof REFRESH_UNRECOVERABLE_CODES[number])) {\n await this.teardownTokens(ctx, output.errorCode);\n return false;\n }\n this.scheduleRefreshRetry(ctx, opts.reason, output.retryAfterSec);\n return false;\n }\n\n this.accessToken = output.accessToken;\n this.persistTokens(ctx, output.accessToken, output.expiresInSec);\n await this.ensureRefreshScheduling(ctx, 'manual');\n\n ctx.bus.emit('auth:tokens:updated', {\n accessToken: output.accessToken,\n refreshToken: output.refreshToken ?? '',\n expSec:\n ctx.engine.configurationContext.configuration.tokens?.accessTokenExpSec,\n });\n\n return true;\n }\n\n private scheduleRefreshRetry(ctx: OrchestratorContext, reason: TokenReason, retryAfterSec?: number) {\n if (this.refreshRetryScheduler) {\n this.refreshRetryScheduler.stop();\n }\n\n const delayMs = this.computeRefreshRetryMs(ctx, reason, retryAfterSec);\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\n\n this.refreshRetryScheduler = new Scheduler()\n .schedule(() => {\n void this.requestRefresh(ctx, { force: true, reason: 'retry' }).then(\n (ok) => {\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\n },\n );\n }, sec)\n .start();\n }\n\n /**\n * Computes delay in ms for the next refresh retry, and logs it.\n * If retryAfterSec is valid (e.g. from 429 Retry-After), uses that (clamped by config);\n * otherwise uses default backoff (base + jitter, cap by config).\n */\n private computeRefreshRetryMs(\n ctx: OrchestratorContext,\n reason: TokenReason,\n retryAfterSec?: number,\n ): number {\n const loader = ctx.engine.configurationContext.loader;\n const retryAfterMinSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_RETRY_AFTER_MIN_SEC',\n { defaultValue: 1 },\n );\n const retryAfterMaxSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_RETRY_AFTER_MAX_SEC',\n { defaultValue: 300 },\n );\n const retryBaseSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_RETRY_BASE_SEC',\n { defaultValue: 2 },\n );\n const retryJitterSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_RETRY_JITTER_SEC',\n { defaultValue: 1 },\n );\n const retryMaxSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_RETRY_MAX_SEC',\n { defaultValue: 30 },\n );\n\n const valid = typeof retryAfterSec === 'number' && Number.isFinite(retryAfterSec) && retryAfterSec >= 0;\n\n if (valid) {\n const delayMs = Math.min(\n retryAfterMaxSec * 1000,\n Math.max(retryAfterMinSec * 1000, retryAfterSec! * 1000),\n );\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\n ctx.notifier.warn(\n `Auth: refresh retry scheduled in ${sec}s (honoring Retry-After, ${reason})`,\n { scope: NotifyScope.System, category: ['token-refresh'], groupKey: 'auth:refresh-retry' },\n );\n return delayMs;\n }\n\n const delayMs = Math.min(\n retryMaxSec * 1000,\n retryBaseSec * 1000 + Math.floor(Math.random() * (retryJitterSec + 1)) * 1000,\n );\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\n ctx.notifier.warn(\n `Auth: refresh retry scheduled in ${sec}s (${reason})`,\n { scope: NotifyScope.System, category: ['token-refresh'], groupKey: 'auth:refresh-retry' },\n );\n return delayMs;\n }\n\n // --- scheduling ---\n private async ensureRefreshScheduling(\n ctx: OrchestratorContext,\n reason: TokenReason,\n ) {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value) return;\n\n if (this.accessToken && !ctx.engine.configurationContext.configuration.tokens?.accessTokenExpSec) {\n this.ensureAccessExpPersisted(ctx, reason);\n }\n\n this.scheduleSilentRefresh(ctx, reason);\n }\n\n private async scheduleSilentRefresh(ctx: OrchestratorContext, reason: TokenReason) {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value) return;\n\n if (this.refreshScheduler) this.refreshScheduler.stop();\n\n const loader = ctx.engine.configurationContext.loader;\n const minDelaySec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_MIN_DELAY_SEC',\n { defaultValue: 2 },\n );\n\n const cfg = ctx.engine.configurationContext.configuration;\n const jwt = this.accessToken;\n const exp =\n cfg.tokens?.accessTokenExpSec ?? (jwt ? this.tryDecodeExp(jwt) : null);\n\n const plannedExp = exp ?? null;\n const groupKey = this.getRefreshGroupKey(ctx);\n\n if (\n this.lastRefreshPlan &&\n this.lastRefreshPlan.exp === plannedExp &&\n this.lastRefreshPlan.groupKey === groupKey\n ) {\n // already scheduled/logged this plan \u2192 don\u2019t duplicate\n return;\n }\n\n this.lastRefreshPlan = { exp: plannedExp, groupKey };\n\n // \uD83D\uDD01 local helper captures everything it needs\n const start = (opts: {\n delaySec: number;\n force: boolean;\n log?: (remainingSec: number) => void;\n }) => {\n let s = new Scheduler().schedule(() => {\n void this.requestRefresh(ctx, {\n force: opts.force,\n reason: 'timer',\n }).then((ok) => {\n if (ok) {\n ctx.notifier.success(\n 'Auth: refresh completed',\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\n );\n }\n });\n }, opts.delaySec);\n\n if (opts.log) {\n s = s.onStep((_step, remainingSec) => opts.log!(remainingSec));\n }\n\n this.refreshScheduler = s.start();\n };\n\n // \u2500\u2500 Case 1: no exp \u2192 minimal delay, forced refresh\n if (!exp) {\n ctx.notifier.info(\n `Auth: no exp; scheduling refresh in ${minDelaySec}s [${reason}]`,\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\n );\n\n start({\n delaySec: minDelaySec,\n force: true,\n });\n\n return;\n }\n\n // \u2500\u2500 Case 2: exp-based scheduling with margin + jitter\n const now = Math.floor(Date.now() / 1000);\n const marginSec = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_MARGIN_SEC',\n { defaultValue: 5 },\n );\n const jitterSecMax = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_JITTER_SEC',\n { defaultValue: 2 },\n );\n const jitter =\n jitterSecMax > 0 ? Math.floor(Math.random() * (jitterSecMax + 1)) : 0;\n\n const targetSec = exp - marginSec - jitter;\n const refreshInSec = Math.max(minDelaySec, targetSec - now);\n\n ctx.notifier.info(\n `Auth: refresh scheduled in ${refreshInSec}s (exp=${exp} now=${now} margin=${marginSec} jitter=${jitter}) [${reason}]`,\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\n );\n\n start({\n delaySec: refreshInSec,\n force: false,\n log: (remainingSec) => {\n ctx.notifier.info(\n `Auth: refresh scheduled in ${remainingSec}s (exp=${exp} now=${now} margin=${marginSec} jitter=${jitter}) [${reason}]`,\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\n );\n },\n });\n }\n\n private getRefreshGroupKey(ctx: OrchestratorContext): string {\n this.refreshCycle++;\n return `${this.refreshGroupKey}:${this.refreshCycle}`;\n }\n\n private async shouldRefreshNow(ctx: OrchestratorContext): Promise<{\n ok: boolean;\n reason: string;\n }> {\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\n if (!refreshRes.ok || !refreshRes.value)\n return { ok: false, reason: 'no_refresh_token' };\n\n const cfg = ctx.engine.configurationContext.configuration;\n const jwt = this.accessToken;\n const exp =\n cfg.tokens?.accessTokenExpSec ?? (jwt ? this.tryDecodeExp(jwt) : null);\n if (!exp) return { ok: true, reason: 'no_exp_assume_refresh' };\n\n const now = Math.floor(Date.now() / 1000);\n const loader = ctx.engine.configurationContext.loader;\n const margin = loader.getConfigValue<number>(\n 'DL_ACCESS_REFRESH_MARGIN_SEC',\n { defaultValue: 300 },\n );\n const remaining = exp - now;\n\n if (remaining <= margin)\n return {\n ok: true,\n reason: `within_margin remaining=${remaining}s margin=${margin}s`,\n };\n return {\n ok: false,\n reason: `too_early remaining=${remaining}s margin=${margin}s`,\n };\n }\n\n // --- token persistence ---\n private ensureAccessExpPersisted(\n ctx: OrchestratorContext,\n reason: TokenReason,\n ) {\n const cfg = ctx.engine.configurationContext.configuration;\n const access = this.accessToken;\n const curExp = cfg.tokens?.accessTokenExpSec;\n\n if (!access) return;\n if (typeof curExp === 'number' && Number.isFinite(curExp)) return;\n\n const exp = this.tryDecodeExp(access);\n if (!exp) return;\n\n const updated: Configuration = {\n ...cfg,\n tokens: { ...(cfg.tokens ?? {}), accessTokenExpSec: exp },\n };\n\n ctx.engine.applyConfiguration(updated);\n ctx.bus.emit('config:save:requested', updated);\n\n ctx.notifier.info(\n `Auth: derived accessTokenExpSec=${exp} (${reason})`,\n { scope: NotifyScope.System },\n );\n }\n\n private persistTokens(\n ctx: OrchestratorContext,\n accessToken: string,\n expiresInSec?: number,\n ) {\n const cfg = ctx.engine.configurationContext.configuration;\n\n const expFromJwt = this.tryDecodeExp(accessToken);\n const expFallback =\n typeof expiresInSec === 'number' && Number.isFinite(expiresInSec)\n ? Math.floor(Date.now() / 1000) + expiresInSec\n : undefined;\n\n const updated: Configuration = {\n ...cfg,\n tokens: {\n ...(cfg.tokens ?? {}),\n accessTokenExpSec: expFromJwt ?? expFallback,\n },\n };\n\n ctx.engine.applyConfiguration(updated);\n ctx.bus.emit('config:save:requested', updated);\n\n ctx.notifier.info(\n `Auth: tokens updated exp=${updated.tokens?.accessTokenExpSec ?? '-'}`,\n { scope: NotifyScope.System },\n );\n }\n\n private async teardownTokens(ctx: OrchestratorContext, why: string) {\n this.accessToken = undefined;\n const cfg = ctx.engine.configurationContext.configuration;\n const updated: Configuration = { ...cfg, tokens: undefined };\n\n ctx.engine.applyConfiguration(updated);\n ctx.bus.emit('config:save:requested', updated);\n\n this.clearTimers();\n this.resetConnectionState();\n\n ctx.bus.emit('auth:signout:requested', void 0);\n ctx.notifier.warn(\n `Auth: signed out (${why}). Please run signin.`,\n );\n }\n\n // --- helpers ---\n private tryDecodeExp(jwt: string): number | null {\n try {\n const payload = decodeJwt(jwt);\n return typeof payload.exp === 'number' ? payload.exp : null;\n } catch {\n return null;\n }\n }\n\n private send(ctx: OrchestratorContext, msg: unknown) {\n ctx.bus.emit('ws:tx', { text: JSON.stringify(msg) });\n }\n\n private resetConnectionState() {\n this.connectionId = null;\n this.sessionId = null;\n this.phase = 'IDLE';\n }\n\n private clearTimers() {\n if (this.refreshScheduler) {\n this.refreshScheduler.stop();\n this.refreshScheduler = null;\n }\n if (this.refreshRetryScheduler) {\n this.refreshRetryScheduler.stop();\n this.refreshRetryScheduler = null;\n }\n if (this.conflictTimer) clearTimeout(this.conflictTimer);\n\n this.conflictTimer = null;\n this.pendingConflictRequest = null;\n }\n}\n", "// agent/src/protocol/messages.ts\r\nimport { z } from \"zod\";\r\n\r\n/**\r\n * Shared defs\r\n */\r\nexport const ToolDef = z.object({\r\n name: z.string().min(1),\r\n description: z.string().optional(),\r\n inputSchema: z.any().optional(),\r\n outputSchema: z.any().optional(),\r\n defaults: z.record(z.string(), z.unknown()).optional(),\r\n version: z.string().optional(),\r\n errorCodes: z.array(z.string()).optional(),\r\n});\r\nexport type ToolDef = z.infer<typeof ToolDef>;\r\n\r\nexport const DirectoryDef = z.object({\r\n id: z.string().min(1),\r\n name: z.string().min(1),\r\n path: z.string().optional(),\r\n path_hint: z.string().optional(),\r\n policy: z.any().optional(),\r\n});\r\nexport type DirectoryDef = z.infer<typeof DirectoryDef>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * connect\r\n */\r\nexport const ConnectRequestSchema = z\r\n .object({\r\n type: z.literal(\"connect\"),\r\n device_id: z.string().min(1),\r\n\r\n agent_version: z.string().min(1),\r\n platform: z.string().optional(),\r\n hostname: z.string().optional(),\r\n device_tag: z.string().optional(),\r\n\r\n // PoP signature (required)\r\n ts: z.number(), // ms epoch\r\n nonce: z.string().min(8),\r\n sig: z.string().min(16), // base64\r\n\r\n // auth tokens (optional at connect)\r\n access_token: z.string().optional(),\r\n refresh_token: z.string().min(20).optional(),\r\n\r\n // optional: bootstrap key if server doesn't have it yet\r\n public_key_pem: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ConnectRequest = z.infer<typeof ConnectRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * connect_ack\r\n */\r\nconst ConnectAckOkSchema = z\r\n .object({\r\n type: z.literal(\"connect_ack\"),\r\n ok: z.literal(true),\r\n session_id: z.string().min(1),\r\n device_id: z.string().min(1),\r\n server_time: z.number(),\r\n\r\n auth: z.object({\r\n device_proof: z.literal(\"ok\"),\r\n access_token: z.enum([\"ok\", \"expired\", \"invalid\", \"missing\"]),\r\n }),\r\n\r\n // client should do next\r\n next: z.array(z.enum([\"refresh_access_token\", \"session_init\"])).min(1),\r\n\r\n // optional hint\r\n workspace_id: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ConnectAckOk = z.infer<typeof ConnectAckOkSchema>;\r\n\r\nconst ConnectAckErrSchema = z\r\n .object({\r\n type: z.literal(\"connect_ack\"),\r\n ok: z.literal(false),\r\n session_id: z.string().optional(),\r\n server_time: z.number(),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\nexport type ConnectAckErr = z.infer<typeof ConnectAckErrSchema>;\r\n\r\nexport const ConnectAckSchema = z.union([ConnectAckOkSchema, ConnectAckErrSchema]);\r\nexport type ConnectAck = z.infer<typeof ConnectAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * refresh_access_token\r\n */\r\nexport const RefreshAccessTokenRequestSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token\"),\r\n device_id: z.string().min(1),\r\n\r\n ts: z.number(), // ms epoch\r\n nonce: z.string().min(8),\r\n\r\n refresh_token: z.string().min(20),\r\n sig: z.string().min(16), // base64 signature over device_id|ts|nonce|sha256(refresh_token)\r\n\r\n session_id: z.string().min(1).optional(),\r\n })\r\n .strict();\r\nexport type RefreshAccessTokenRequest = z.infer<typeof RefreshAccessTokenRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * refresh_access_token_ack\r\n */\r\nconst RefreshAckOkSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token_ack\"),\r\n ok: z.literal(true),\r\n access_token: z.string().min(1),\r\n refresh_token: z.string().min(20), // rotated\r\n expires_in_sec: z.number().int().positive().optional(),\r\n next: z.array(z.literal(\"session_init\")).default([\"session_init\"]),\r\n })\r\n .strict();\r\n\r\nconst RefreshAckErrSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token_ack\"),\r\n ok: z.literal(false),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const RefreshAccessTokenAckSchema = z.union([RefreshAckOkSchema, RefreshAckErrSchema]);\r\nexport type RefreshAccessTokenAck = z.infer<typeof RefreshAccessTokenAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * session_init\r\n */\r\nexport const SessionInitRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_init\"),\r\n device_id: z.string().min(1),\r\n session_id: z.string().min(1),\r\n })\r\n .strict();\r\nexport type SessionInitRequest = z.infer<typeof SessionInitRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_init_ack\r\n */\r\nconst SessionInitAckOkSchema = z\r\n .object({\r\n type: z.literal(\"session_init_ack\"),\r\n ok: z.literal(true),\r\n device_id: z.string().min(1),\r\n session_id: z.string().min(1),\r\n mode: z.enum([\"ACTIVE\", \"ACTIVE_RECLAIMED\", \"STANDBY\"]),\r\n reason: z.string().optional(),\r\n server_time: z.number(),\r\n\r\n next: z.array(z.enum([\"tools_publish\", \"directories_publish\"])).optional(),\r\n })\r\n .strict();\r\n\r\nconst SessionInitAckErrSchema = z\r\n .object({\r\n type: z.literal(\"session_init_ack\"),\r\n ok: z.literal(false),\r\n device_id: z.string().min(1),\r\n server_time: z.number(),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const SessionInitAckSchema = z.union([SessionInitAckOkSchema, SessionInitAckErrSchema]);\r\nexport type SessionInitAck = z.infer<typeof SessionInitAckSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_conflict (server prompts new connection)\r\n */\r\nexport const SessionConflictRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict\"),\r\n device_id: z.string().min(1),\r\n new_session_id: z.string().min(1),\r\n\r\n max_sessions: z.number().int().positive(),\r\n active_count: z.number().int().nonnegative(),\r\n\r\n deadline_ms: z.number().int().positive(),\r\n message: z.string().min(1),\r\n\r\n choices: z\r\n .array(\r\n z.object({\r\n id: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n default: z.boolean().optional(),\r\n prompt: z.string().optional(),\r\n })\r\n )\r\n .min(1),\r\n })\r\n .strict();\r\nexport type SessionConflictRequest = z.infer<typeof SessionConflictRequestSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * session_conflict_resolve\r\n */\r\nexport const SessionConflictResolveRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve\"),\r\n device_id: z.string().min(1),\r\n new_session_id: z.string().min(1),\r\n choice: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n })\r\n .strict();\r\nexport type SessionConflictResolveRequest = z.infer<typeof SessionConflictResolveRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_conflict_resolve_ack\r\n */\r\nconst SessionConflictResolveAckOkSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve_ack\"),\r\n ok: z.literal(true),\r\n device_id: z.string().min(1),\r\n choice: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n next: z.array(z.enum([\"session_init\"])).optional(),\r\n })\r\n .strict();\r\n\r\nconst SessionConflictResolveAckErrSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve_ack\"),\r\n ok: z.literal(false),\r\n device_id: z.string().min(1),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const SessionConflictResolveAckSchema = z.union([\r\n SessionConflictResolveAckOkSchema,\r\n SessionConflictResolveAckErrSchema,\r\n]);\r\nexport type SessionConflictResolveAck = z.infer<typeof SessionConflictResolveAckSchema>;\r\n\r\nexport const QuiesceRequestSchema = z.object({\r\n type: z.literal(\"quiesce\"),\r\n session_id: z.string().min(1),\r\n reason: z.enum([\"SESSION_REPLACED\"]),\r\n deadline_ms: z.number().int().positive(),\r\n}).strict();\r\n\r\nexport type QuiesceRequest = z.infer<typeof QuiesceRequestSchema>;\r\n\r\nexport const QuiesceAckSchema = z.object({\r\n type: z.literal(\"quiesce_ack\"),\r\n session_id: z.string().min(1),\r\n status: z.enum([\"IDLE\", \"BUSY\"]),\r\n}).strict();\r\n\r\nexport type QuiesceAck = z.infer<typeof QuiesceAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * tools_publish (+ ack)\r\n */\r\nexport const ToolsPublishRequestSchema = z\r\n .object({\r\n type: z.literal(\"tools_publish\"),\r\n device_id: z.string().min(1),\r\n workspace_id: z.string().optional(),\r\n tools: z.array(ToolDef).default([]),\r\n tools_version: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ToolsPublishRequest = z.infer<typeof ToolsPublishRequestSchema>;\r\n\r\nexport const ToolsPublishAckSchema = z\r\n .object({\r\n type: z.literal(\"tools_publish_ack\"),\r\n ok: z.boolean(),\r\n device_id: z.string().min(1),\r\n tools_version: z.string().optional(),\r\n error: z.object({ code: z.string().min(1), message: z.string().min(1) }).optional(),\r\n })\r\n .strict();\r\nexport type ToolsPublishAck = z.infer<typeof ToolsPublishAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * directories_publish (+ ack)\r\n */\r\nexport const DirectoriesPublishRequestSchema = z\r\n .object({\r\n type: z.literal(\"directories_publish\"),\r\n device_id: z.string().min(1),\r\n workspace_id: z.string().optional(),\r\n directories: z.array(DirectoryDef).default([]),\r\n })\r\n .strict();\r\nexport type DirectoriesPublishRequest = z.infer<typeof DirectoriesPublishRequestSchema>;\r\n\r\nexport const DirectoriesPublishAckSchema = z\r\n .object({\r\n type: z.literal(\"directories_publish_ack\"),\r\n ok: z.boolean(),\r\n device_id: z.string().min(1),\r\n error: z.object({ code: z.string().min(1), message: z.string().min(1) }).optional(),\r\n })\r\n .strict();\r\nexport type DirectoriesPublishAck = z.infer<typeof DirectoriesPublishAckSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * tool_call (agent executes and replies tool_result)\r\n */\r\nexport const ToolCallRequestSchema = z\r\n .object({\r\n type: z.literal(\"tool_call\"),\r\n job_id: z.string().min(1),\r\n\r\n device_id: z.string().min(1).optional(),\r\n workspace_id: z.string().optional(),\r\n\r\n tool: z.string().min(1),\r\n args: z.record(z.string(), z.unknown()).default({}),\r\n })\r\n .strict();\r\nexport type ToolCallRequest = z.infer<typeof ToolCallRequestSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * tool_result\r\n */\r\nexport const ToolMessage = z.object({\r\n type: z.enum([\"error\", \"warning\", \"info\"]),\r\n description: z.string().min(1),\r\n});\r\nexport type ToolMessage = z.infer<typeof ToolMessage>;\r\n\r\nexport const ToolResultResponseSchema = z\r\n .object({\r\n type: z.literal(\"tool_result\"),\r\n job_id: z.string().min(1),\r\n tool: z.string().min(1),\r\n\r\n ok: z.boolean(),\r\n result: z.unknown().optional(),\r\n error: z.unknown().optional(),\r\n\r\n messages: z.array(ToolMessage).optional(),\r\n timing: z\r\n .object({\r\n execution_ms: z.number(),\r\n execution_sec: z.number(),\r\n })\r\n .optional(),\r\n })\r\n .strict()\r\n .superRefine((data, ctx) => {\r\n if (data.ok && data.result === undefined) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: \"tool_result ok=true should include result\",\r\n path: [\"result\"],\r\n });\r\n }\r\n if (!data.ok && data.error === undefined) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: \"tool_result ok=false should include error\",\r\n path: [\"error\"],\r\n });\r\n }\r\n });\r\nexport type ToolResultResponse = z.infer<typeof ToolResultResponseSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * disconnect_notice (server hint before close)\r\n */\r\nexport const DisconnectNoticeResponseSchema = z\r\n .object({\r\n type: z.literal(\"disconnect_notice\"),\r\n code: z.number().int(),\r\n reason: z.string(),\r\n at: z.number(), // server time ms\r\n })\r\n .strict();\r\nexport type DisconnectNoticeResponse = z.infer<typeof DisconnectNoticeResponseSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * promoted_active / demoted_standby (slot changes)\r\n * (Keep these if your server uses them; otherwise remove.)\r\n */\r\nexport const PromotedActiveResponseSchema = z\r\n .object({\r\n type: z.literal(\"promoted_active\"),\r\n workspaceId: z.string().min(1),\r\n })\r\n .strict();\r\nexport type PromotedActiveResponse = z.infer<typeof PromotedActiveResponseSchema>;\r\n\r\nexport const DemotedStandbyResponseSchema = z\r\n .object({\r\n type: z.literal(\"demoted_standby\"),\r\n workspaceId: z.string().min(1),\r\n })\r\n .strict();\r\nexport type DemotedStandbyResponse = z.infer<typeof DemotedStandbyResponseSchema>;\r\n\r\n/**\r\n * Union types\r\n *\r\n * AgentOutbound = what agent sends to bridge\r\n * BridgeOutbound = what bridge sends to agent\r\n */\r\nexport const BridgeInboundMsgSchema = z.union([\r\n ConnectRequestSchema,\r\n RefreshAccessTokenRequestSchema,\r\n SessionInitRequestSchema,\r\n SessionConflictResolveRequestSchema,\r\n ToolsPublishRequestSchema,\r\n DirectoriesPublishRequestSchema,\r\n ToolCallRequestSchema,\r\n ToolResultResponseSchema,\r\n QuiesceAckSchema,\r\n DisconnectNoticeResponseSchema,\r\n PromotedActiveResponseSchema,\r\n DemotedStandbyResponseSchema,\r\n]);\r\nexport type BridgeInboundMsg = z.infer<typeof BridgeInboundMsgSchema>;\r\n\r\nexport const BridgeOutboundMsgSchema = z.union([\r\n ConnectAckSchema,\r\n RefreshAccessTokenAckSchema,\r\n SessionInitAckSchema,\r\n SessionConflictRequestSchema,\r\n SessionConflictResolveAckSchema,\r\n ToolsPublishAckSchema,\r\n DirectoriesPublishAckSchema,\r\n ToolCallRequestSchema, \r\n QuiesceRequestSchema,\r\n DisconnectNoticeResponseSchema,\r\n PromotedActiveResponseSchema,\r\n DemotedStandbyResponseSchema,\r\n]);\r\nexport type BridgeOutboundMsg = z.infer<typeof BridgeOutboundMsgSchema>;\r\n", "import { z } from \"zod\";\r\n\r\n// ---- Start ----\r\nexport const DeviceAuthStartRequestSchema = z.object({\r\n device_id: z.string().optional(),\r\n device_name: z.string().optional(),\r\n platform: z.string().optional(),\r\n public_key_pem: z.string().min(1),\r\n});\r\nexport type DeviceAuthStartRequest = z.infer<typeof DeviceAuthStartRequestSchema>;\r\n\r\nexport const DeviceAuthStartResponseSchema = z.object({\r\n device_code: z.string(),\r\n user_code: z.string(),\r\n verification_uri: z.string(),\r\n verification_uri_complete: z.string(),\r\n expires_in: z.number(),\r\n interval: z.number(),\r\n challenge_id: z.string(),\r\n challenge: z.string(), // base64url\r\n});\r\nexport type DeviceAuthStartResponse = z.infer<typeof DeviceAuthStartResponseSchema>;\r\n\r\n// ---- Stream (STATUS ONLY) ----\r\n// What SSE returns in data: snapshots/errors only\r\nexport const DeviceAuthStreamResponseSchema = z.union([\r\n z.object({\r\n status: z.literal(\"pending\"),\r\n needs_proof: z.boolean(),\r\n }),\r\n z.object({\r\n status: z.literal(\"approved\"),\r\n needs_proof: z.boolean(),\r\n }),\r\n z.object({\r\n error: z.literal(\"access_denied\"),\r\n }),\r\n z.object({\r\n error: z.literal(\"expired_token\"),\r\n }),\r\n]);\r\n\r\nexport type DeviceAuthStreamRequest = {\r\n deviceCode: string;\r\n timeoutMs: number;\r\n signal?: AbortSignal;\r\n};\r\n\r\nexport type DeviceAuthStreamResponse = z.infer<typeof DeviceAuthStreamResponseSchema>;\r\n\r\n// ---- Prove ----\r\nexport const DeviceAuthProveRequestSchema = z.object({\r\n device_code: z.string(),\r\n challenge_id: z.string(),\r\n challenge: z.string(), \r\n signature_b64: z.string() \r\n});\r\nexport type DeviceAuthProveRequest = z.infer<typeof DeviceAuthProveRequestSchema>;\r\n\r\nexport const DeviceAuthProveResponseSchema = z.object({\r\n ok: z.literal(true),\r\n});\r\nexport type DeviceAuthProveResponse = z.infer<typeof DeviceAuthProveResponseSchema>;\r\n\r\n// ---- Token ----\r\nexport const DeviceAuthTokenRequestSchema = z.object({\r\n device_code: z.string(),\r\n});\r\nexport type DeviceAuthTokenRequest = z.infer<typeof DeviceAuthTokenRequestSchema>;\r\n\r\nexport const DeviceAuthTokenResponseSchema = z.object({\r\n access_token: z.string(),\r\n refresh_token: z.string(), \r\n token_type: z.literal(\"Bearer\"),\r\n expires_in: z.number(),\r\n device_id: z.string(),\r\n});\r\nexport type DeviceAuthTokenResponse = z.infer<typeof DeviceAuthTokenResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshRequestSchema = z.object({\r\n device_id: z.string().min(1),\r\n refresh_token: z.string().min(1),\r\n ts: z.number().int(),\r\n nonce: z.string().min(8),\r\n sig: z.string().min(16), // base64\r\n});\r\n\r\nexport type DeviceAuthRefreshRequest = z.infer<typeof DeviceAuthRefreshRequestSchema>;\r\n\r\nexport const DeviceAuthRefreshSuccessResponseSchema = z.object({\r\n ok: z.literal(true),\r\n access_token: z.string().min(10),\r\n refresh_token: z.string().min(10),\r\n expires_in_sec: z.number().int().positive(),\r\n device_id: z.string().min(1),\r\n});\r\nexport type DeviceAuthRefreshSuccessResponse = z.infer<typeof DeviceAuthRefreshSuccessResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshErrorResponseSchema = z.object({\r\n ok: z.literal(false),\r\n error: z.object({\r\n code: z.string(),\r\n message: z.string(),\r\n }),\r\n});\r\nexport type DeviceAuthRefreshErrorResponse = z.infer<typeof DeviceAuthRefreshErrorResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshResponseSchema = z.union([DeviceAuthRefreshSuccessResponseSchema, DeviceAuthRefreshErrorResponseSchema]);\r\n\r\nexport type DeviceAuthRefreshResponse = z.infer<typeof DeviceAuthRefreshResponseSchema>;\r\n", "/**\n * Base types for all filesystem tools\n * Following SOLID and DRY principles - all shared types are defined here\n */\n\n// ============================================================================\n// Base Args Types\n// ============================================================================\n\n/**\n * Base arguments that all filesystem tools share\n */\nexport type BaseFsArgs = {\n directory_id: string;\n workspace_id?: string;\n device_id?: string;\n};\n\n/**\n * Base arguments for tools that operate on a specific path\n */\nexport type BaseFsPathArgs = BaseFsArgs & {\n path: string;\n};\n\n/**\n * Base arguments for tools that optionally operate on a path\n */\nexport type BaseFsOptionalPathArgs = BaseFsArgs & {\n path?: string;\n};\n\n/**\n * Common filtering options\n */\nexport type FsFilterOptions = {\n only?: 'all' | 'files' | 'dirs';\n include_hidden?: boolean;\n};\n\n/**\n * Common pagination options\n */\nexport type FsPaginationOptions = {\n limit?: number;\n offset?: number;\n};\n\n/**\n * Common sorting options\n */\nexport type FsSortOptions = {\n sort?: 'name' | 'mtime' | 'size';\n order?: 'asc' | 'desc';\n};\n\n/**\n * Common detail level options\n */\nexport type FsDetailOptions = {\n detail?: 'basic' | 'stat' | 'digest';\n};\n\n// ============================================================================\n// Common Output Types\n// ============================================================================\n\n/**\n * Standard entry shape for all filesystem list/tree/search operations\n */\nexport type FsEntry = {\n name: string;\n path: string; // relative to root\n type: 'file' | 'dir' | 'symlink' | 'other';\n size?: number; // file only\n mtime?: number; // epoch seconds\n ext?: string; // optional helper (file extension)\n hidden?: boolean; // if included\n ignored?: boolean; // normally filtered, but helpful for debug\n};\n\n/**\n * Standard pagination metadata\n */\nexport type PaginationMeta = {\n count: number; // items in this response\n limit: number; // max items requested\n offset: number; // offset used\n has_more: boolean; // whether more items exist\n next_offset?: number; // next offset to use (if has_more)\n};\n\n/**\n * Standard context metadata for filesystem operations\n */\nexport type FsContext = {\n workspace_id?: string;\n device_id?: string;\n directory_id: string;\n path: string; // relative path within directory\n};\n\n/**\n * Standard filtered metadata (for ignore system)\n */\nexport type FilteredMeta = {\n ignored_count: number; // number of entries filtered by ignore rules\n rules_count?: number; // number of ignore rules applied (for debug)\n};\n\n/**\n * Standard summary statistics for directory listings\n */\nexport type FsSummary = {\n total_entries: number;\n files: number;\n dirs: number;\n symlinks: number;\n hidden: number;\n ignored: number;\n by_ext?: Array<{ ext: string; count: number }>; // top N extensions\n total_file_bytes?: number; // only if detail=\"stat\" or \"digest\"\n};\n\n// ============================================================================\n// Tool Result Envelope\n// ============================================================================\n\n/**\n * Standard error shape for tool results\n */\nexport type ToolError = {\n code: string; // error code (e.g., \"PATH_ESCAPE\", \"NOT_FOUND\", \"PERMISSION_DENIED\")\n message: string; // human-readable message\n details?: Record<string, unknown>; // optional additional context\n};\n\n/**\n * Standard result envelope - success case\n */\nexport type ToolOk<T> = {\n ok: true;\n data: T;\n};\n\n/**\n * Standard result envelope - failure case\n */\nexport type ToolFail = {\n ok: false;\n error: ToolError;\n};\n\n/**\n * Standard result envelope - union type\n */\nexport type ToolResult<T> = ToolOk<T> | ToolFail;\n\n/**\n * Helper to create success result\n */\nexport function ok<T>(data: T): ToolOk<T> {\n return { ok: true, data };\n}\n\n/**\n * Helper to create failure result\n */\nexport function fail(error: ToolError): ToolFail {\n return { ok: false, error };\n}\n", "type StepCallback = (stepSec: number, remainingSec: number) => void;\r\ntype TaskCallback = () => void;\r\n\r\nexport class Scheduler {\r\n private timeout: NodeJS.Timeout | null = null;\r\n private interval: NodeJS.Timeout | null = null;\r\n private totalSec = 0;\r\n private remainingSec = 0;\r\n private stepSec = 1;\r\n private task: TaskCallback | null = null;\r\n private stepCb: StepCallback | null = null;\r\n\r\n /** set interval between steps (default 1s) */\r\n public setStep(sec: number): this {\r\n this.stepSec = Math.max(1, sec);\r\n return this;\r\n }\r\n\r\n /** schedule the main task to run after delaySec seconds */\r\n public schedule(task: TaskCallback, delaySec: number): this {\r\n this.task = task;\r\n this.totalSec = delaySec;\r\n this.remainingSec = delaySec;\r\n return this;\r\n }\r\n\r\n /** callback called every step */\r\n public onStep(cb: StepCallback): this {\r\n this.stepCb = cb;\r\n return this;\r\n }\r\n\r\n /** start counting down */\r\n public start(): this {\r\n this.clear();\r\n\r\n if (this.remainingSec <= 0) {\r\n this.runTask();\r\n return this;\r\n }\r\n\r\n // call step callback immediately\r\n this.stepCb?.(this.stepSec, this.remainingSec);\r\n\r\n this.interval = setInterval(() => {\r\n this.remainingSec -= this.stepSec;\r\n if (this.remainingSec <= 0) {\r\n this.runTask();\r\n } else {\r\n this.stepCb?.(this.stepSec, this.remainingSec);\r\n }\r\n }, this.stepSec * 1000);\r\n\r\n return this;\r\n }\r\n\r\n /** stop/cancel the timer */\r\n public stop(): this {\r\n this.clear();\r\n return this;\r\n }\r\n\r\n /** reset and start over */\r\n public restart(): this {\r\n this.remainingSec = this.totalSec;\r\n return this.start();\r\n }\r\n\r\n /** internal task runner */\r\n private runTask() {\r\n this.clear();\r\n if (this.task) {\r\n try {\r\n this.task();\r\n } catch (err) {\r\n throw new Error(`Scheduler task failed: ${err}`);\r\n }\r\n }\r\n }\r\n\r\n /** clear all timers */\r\n private clear() {\r\n if (this.timeout) {\r\n clearTimeout(this.timeout);\r\n this.timeout = null;\r\n }\r\n if (this.interval) {\r\n clearInterval(this.interval);\r\n this.interval = null;\r\n }\r\n }\r\n}\r\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsListOutput, FsListArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\ntype FsEntry = {\n name: string;\n path: string;\n type: 'file' | 'dir' | 'symlink' | 'other';\n size?: number;\n mtime?: number;\n ext?: string;\n hidden?: boolean;\n ignored?: boolean;\n};\n\nfunction sortEntries(entries: FsEntry[], sort: 'name' | 'mtime' | 'size', order: 'asc' | 'desc'): FsEntry[] {\n const sorted = [...entries];\n const multiplier = order === 'asc' ? 1 : -1;\n\n sorted.sort((a, b) => {\n if (sort === 'name') {\n return multiplier * a.name.localeCompare(b.name);\n }\n if (sort === 'mtime') {\n const aTime = a.mtime ?? 0;\n const bTime = b.mtime ?? 0;\n return multiplier * (aTime - bTime);\n }\n if (sort === 'size') {\n const aSize = a.size ?? 0;\n const bSize = b.size ?? 0;\n return multiplier * (aSize - bSize);\n }\n return 0;\n });\n\n return sorted;\n}\n\nfunction filterEntries(entries: FsEntry[], only: 'all' | 'files' | 'dirs'): FsEntry[] {\n if (only === 'all') return entries;\n if (only === 'files') {\n return entries.filter((e) => e.type === 'file' || e.type === 'symlink');\n }\n if (only === 'dirs') {\n return entries.filter((e) => e.type === 'dir');\n }\n return entries;\n}\n\n/**\n * Executer for fs_list tool\n */\nexport class FsListExecuter extends BaseExecuter<FsListArgs, FsListOutput> {\n protected async executeTool(args: FsListArgs): Promise<FsListOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path);\n\n const limit = Math.min(Math.max(args.limit ?? 200, 1), 1000);\n const offset = Math.max(args.offset ?? 0, 0);\n const includeHidden = args.include_hidden ?? false;\n const only = args.only ?? 'all';\n const sort = args.sort ?? 'name';\n const order = args.order ?? 'asc';\n const detail = args.detail ?? 'stat';\n\n // Check that target is a directory\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('list', context, false, 'Path is not a directory.');\n throw toolErr('NOT_A_DIRECTORY', 'Path is not a directory.', {\n path: rel,\n hint: 'The path must point to a directory, not a file. Use fs_read to read files, or provide a directory path for listing.',\n });\n }\n } catch (e: any) {\n // If it's already a ToolError, rethrow\n if (e?.code && e?.message && typeof e?.code === 'string') {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('list', context, false, e.message);\n throw e;\n }\n throw mapFsError(e, 'Failed to list directory.');\n }\n\n // Read directory entries\n let dirents;\n try {\n dirents = await fs.readdir(absTarget, { withFileTypes: true });\n } catch (e) {\n throw mapFsError(e, 'Failed to read directory.');\n }\n\n // Filter hidden unless include_hidden\n let visibleDirents = includeHidden ? dirents : dirents.filter((d) => !d.name.startsWith('.'));\n\n // Build entries with metadata and apply ignore system\n const allEntries: FsEntry[] = [];\n let ignoredCount = 0;\n const summary: FsListOutput['summary'] = {\n total_entries: 0,\n files: 0,\n dirs: 0,\n symlinks: 0,\n hidden: 0,\n ignored: 0,\n total_file_bytes: 0,\n };\n const extCounts = new Map<string, number>();\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n for (const d of visibleDirents) {\n const full = path.join(absTarget, d.name);\n const rawRelPath = rel === '.' ? d.name : path.posix.join(rel, d.name);\n // Normalize to POSIX separators so ignore rules see proper segments\n const entryRelPath = rawRelPath.replace(/\\\\/g, '/');\n\n let type: FsEntry['type'] = 'other';\n if (d.isDirectory()) type = 'dir';\n else if (d.isFile()) type = 'file';\n else if (d.isSymbolicLink()) type = 'symlink';\n\n const isHidden = d.name.startsWith('.');\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, d.isDirectory(), ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n ignoredCount++;\n summary!.ignored++;\n continue; // always filter ignored entries\n }\n\n // Update summary counts\n summary!.total_entries++;\n if (type === 'file') summary!.files++;\n else if (type === 'dir') summary!.dirs++;\n else if (type === 'symlink') summary!.symlinks++;\n if (isHidden) summary!.hidden++;\n\n // Get stat for size/mtime (only if detail requires it)\n let size: number | undefined;\n let mtime: number | undefined;\n if (detail === 'stat' || detail === 'digest') {\n try {\n const st = await fs.stat(full);\n if (st.isFile()) {\n size = st.size;\n summary!.total_file_bytes = (summary!.total_file_bytes ?? 0) + st.size;\n }\n mtime = Math.floor(st.mtimeMs / 1000);\n } catch {\n // Stat failed, continue without size/mtime\n }\n }\n\n // Extract extension and count\n const ext = type === 'file' ? path.extname(d.name).slice(1) : undefined;\n if (ext && (detail === 'stat' || detail === 'digest')) {\n extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n allEntries.push({\n name: d.name,\n path: entryRelPath,\n type,\n size,\n mtime,\n ext,\n hidden: isHidden,\n ignored: false, // already filtered out ignored entries\n });\n }\n\n // Build top extensions list for summary (top 10)\n if (detail === 'digest' && extCounts.size > 0) {\n summary!.by_ext = Array.from(extCounts.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n }\n\n // Apply type filter (files/dirs)\n const filteredEntries = filterEntries(allEntries, only);\n\n // Apply sorting\n const sortedEntries = sortEntries(filteredEntries, sort, order);\n\n // Apply pagination\n const page = sortedEntries.slice(offset, offset + limit);\n const next_offset = offset + page.length;\n const has_more = next_offset < sortedEntries.length;\n\n const meta = {\n count: page.length,\n limit,\n offset,\n has_more,\n next_offset: has_more ? next_offset : undefined,\n };\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n const filtered = { ignored_count: ignoredCount };\n\n const result: FsListOutput = {\n items: page,\n meta,\n context,\n filtered,\n };\n\n // Include summary when detail=\"digest\"\n if (detail === 'digest') {\n result.summary = summary;\n }\n\n // Audit successful list operation\n auditFsOperation('list', context, true, undefined, {\n file_count: page.length,\n });\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_list tool\n */\nexport async function executeFsList(\n config: Configuration,\n args: FsListArgs\n): Promise<ToolResult<FsListOutput>> {\n const executer = new FsListExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\nimport { ok, fail } from '@devicelink-workspace/domain';\nimport type { ToolResult, ToolError } from '@devicelink-workspace/domain';\n\n/**\n * Base class for tool executers\n * Provides common functionality for all executers:\n * - Configuration access\n * - Error handling\n * - Result wrapping\n */\nexport abstract class BaseExecuter<TArgs, TOutput> {\n protected readonly config: Configuration;\n\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Execute the tool with the provided arguments\n * This is the main entry point that handles error handling and result wrapping\n */\n public async execute(args: TArgs): Promise<ToolResult<TOutput>> {\n try {\n const output = await this.executeTool(args);\n return ok(output);\n } catch (e: unknown) {\n if (this.isToolError(e)) {\n return fail(e);\n }\n // Don't leak internal error details (stack traces, OS paths) to MCP clients\n const safeMessage = e instanceof Error ? e.message : 'An unexpected error occurred';\n return fail({\n code: 'INTERNAL',\n message: safeMessage,\n });\n }\n }\n\n /**\n * Abstract method that subclasses must implement\n * This is where the actual tool function is called\n */\n protected abstract executeTool(args: TArgs): Promise<TOutput>;\n\n /**\n * Type guard to check if an error is a ToolError\n */\n protected isToolError(e: unknown): e is ToolError {\n return (\n typeof e === 'object' &&\n e !== null &&\n 'code' in e &&\n 'message' in e &&\n typeof (e as any).code === 'string' &&\n typeof (e as any).message === 'string'\n );\n }\n}\n", "import path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport type { Configuration } from '../../../core/configuration.js';\r\n\r\n/**\r\n * Ignore rule types\r\n */\r\nexport type IgnoreRule = {\r\n pattern: string; // glob pattern or simple string\r\n type: 'glob' | 'exact' | 'prefix';\r\n};\r\n\r\n/**\r\n * Context for ignore checking\r\n */\r\nexport type IgnoreContext = {\r\n directory_id: string;\r\n workspace_id?: string;\r\n directory_path: string; // absolute path to directory\r\n};\r\n\r\n/**\r\n * Result of ignore check\r\n */\r\nexport type IgnoreResult = {\r\n shouldIgnore: boolean;\r\n matchedRule?: string; // which rule matched (for debug)\r\n reason?: string; // reason for ignoring (e.g., 'denylist:secrets')\r\n};\r\n\r\n/**\r\n * High-risk default denylist (security baseline)\r\n * This is evaluated BEFORE user-configurable ignore rules.\r\n * These patterns are always blocked regardless of user configuration.\r\n */\r\nfunction matchesDefaultDenylist(relPath: string): IgnoreResult | null {\r\n const normalized = relPath.replace(/\\\\/g, '/');\r\n \r\n // Prefix rules (match anywhere in path)\r\n if (normalized.includes('/secrets/') || normalized.startsWith('secrets/')) {\r\n return { shouldIgnore: true, reason: 'denylist:secrets', matchedRule: 'secrets/' };\r\n }\r\n if (normalized.includes('/.env') || normalized.startsWith('.env')) {\r\n return { shouldIgnore: true, reason: 'denylist:env', matchedRule: '.env' };\r\n }\r\n if (normalized.includes('/id_rsa') || normalized.endsWith('/id_rsa')) {\r\n return { shouldIgnore: true, reason: 'denylist:ssh', matchedRule: 'id_rsa' };\r\n }\r\n if (normalized.includes('/id_ed25519') || normalized.endsWith('/id_ed25519')) {\r\n return { shouldIgnore: true, reason: 'denylist:ssh', matchedRule: 'id_ed25519' };\r\n }\r\n \r\n // Suffix rules (file extensions)\r\n if (normalized.endsWith('.pem')) {\r\n return { shouldIgnore: true, reason: 'denylist:pem', matchedRule: '*.pem' };\r\n }\r\n if (normalized.endsWith('.key')) {\r\n return { shouldIgnore: true, reason: 'denylist:key', matchedRule: '*.key' };\r\n }\r\n if (normalized.endsWith('.p12')) {\r\n return { shouldIgnore: true, reason: 'denylist:p12', matchedRule: '*.p12' };\r\n }\r\n if (normalized.endsWith('.pfx')) {\r\n return { shouldIgnore: true, reason: 'denylist:pfx', matchedRule: '*.pfx' };\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/**\r\n * Default ignore patterns (applied to all directories)\r\n */\r\nconst DEFAULT_IGNORE_PATTERNS: IgnoreRule[] = [\r\n // Segment-exact directory/file names (match ANY path segment)\r\n { pattern: 'node_modules', type: 'exact' },\r\n { pattern: '.git', type: 'exact' },\r\n { pattern: 'dist', type: 'exact' },\r\n { pattern: 'build', type: 'exact' },\r\n { pattern: '.next', type: 'exact' },\r\n { pattern: '.cache', type: 'exact' },\r\n { pattern: '.DS_Store', type: 'exact' },\r\n { pattern: 'Thumbs.db', type: 'exact' },\r\n\r\n // True globs\r\n { pattern: '*.tmp', type: 'glob' },\r\n { pattern: '*.log', type: 'glob' },\r\n { pattern: '.env*', type: 'glob' },\r\n];\r\n\r\n/**\r\n * Load ignore rules for a directory\r\n *\r\n * Priority:\r\n * 1. Directory-specific ignore file (e.g., .devicelinkignore in directory)\r\n * 2. Workspace-level ignore rules (future: from config)\r\n * 3. Global default patterns\r\n */\r\nexport function loadIgnoreRules(cfg: Configuration, directory_id: string, workspace_id?: string): IgnoreRule[] {\r\n const directory = cfg.directories.find((r) => r.id === directory_id);\r\n if (!directory) {\r\n return DEFAULT_IGNORE_PATTERNS;\r\n }\r\n\r\n const rules: IgnoreRule[] = [];\r\n\r\n // Load directory-specific ignore file\r\n const ignoreFilePath = path.join(directory.path, '.devicelinkignore');\r\n if (fs.existsSync(ignoreFilePath)) {\r\n try {\r\n const content = fs.readFileSync(ignoreFilePath, 'utf-8');\r\n const lines = content\r\n .split('\\n')\r\n .map((line) => line.trim())\r\n .filter((line) => line && !line.startsWith('#'));\r\n\r\n for (const line of lines) {\r\n // Simple pattern detection\r\n if (line.includes('*') || line.includes('?')) {\r\n rules.push({ pattern: line, type: 'glob' });\r\n } else if (line.startsWith('/')) {\r\n // Prefix match\r\n rules.push({ pattern: line.slice(1), type: 'prefix' });\r\n } else {\r\n // Exact or simple match\r\n rules.push({ pattern: line, type: 'exact' });\r\n }\r\n }\r\n } catch (error) {\r\n // If we can't read the ignore file, continue with defaults\r\n console.warn(`[ignore] Failed to read .devicelinkignore: ${error}`);\r\n }\r\n }\r\n\r\n // Future: workspace-level ignore rules from config\r\n // if (workspace_id) { ... }\r\n\r\n // Add defaults last (lowest priority)\r\n rules.push(...DEFAULT_IGNORE_PATTERNS);\r\n\r\n return rules;\r\n}\r\n\r\n/**\r\n * Check if a path should be ignored\r\n *\r\n * @param relPath - Relative path from directory (e.g., \"src/index.ts\" or \"node_modules/package\")\r\n * @param isDir - Whether this is a directory\r\n * @param ctx - Ignore context\r\n * @returns IgnoreResult indicating if path should be ignored\r\n */\r\nexport function shouldIgnore(\r\n relPath: string,\r\n isDir: boolean,\r\n ctx: IgnoreContext,\r\n cfg: Configuration\r\n): IgnoreResult {\r\n // Security baseline denylist first (cannot be overridden)\r\n const denied = matchesDefaultDenylist(relPath);\r\n if (denied) {\r\n return denied;\r\n }\r\n\r\n const rules = loadIgnoreRules(cfg, ctx.directory_id, ctx.workspace_id);\r\n\r\n // Normalize path separators\r\n const normalizedPath = relPath.replace(/\\\\/g, '/');\r\n const pathParts = normalizedPath.split('/').filter(Boolean);\r\n\r\n for (const rule of rules) {\r\n let matched = false;\r\n\r\n if (rule.type === 'exact') {\r\n // Check if any path segment matches exactly\r\n matched = pathParts.some((part) => part === rule.pattern);\r\n } else if (rule.type === 'prefix') {\r\n // Check if path starts with prefix\r\n matched = normalizedPath.startsWith(rule.pattern);\r\n } else if (rule.type === 'glob') {\r\n // If pattern has no slash and no wildcard chars, treat it like segment-exact.\r\n if (!rule.pattern.includes('/') && !rule.pattern.includes('*') && !rule.pattern.includes('?')) {\r\n matched = pathParts.some((part) => part.toLowerCase() === rule.pattern.toLowerCase());\r\n } else {\r\n matched = matchesGlob(normalizedPath, rule.pattern, isDir);\r\n }\r\n }\r\n\r\n if (matched) {\r\n return { shouldIgnore: true, matchedRule: rule.pattern };\r\n }\r\n }\r\n\r\n return { shouldIgnore: false };\r\n}\r\n\r\n/**\r\n * Simple glob matcher\r\n * Supports: *, **, ? patterns\r\n */\r\nfunction matchesGlob(path: string, pattern: string, isDir: boolean): boolean {\r\n // Convert glob to regex\r\n let regexStr = '^';\r\n let i = 0;\r\n\r\n while (i < pattern.length) {\r\n const char = pattern[i];\r\n if (char === '*') {\r\n if (i + 1 < pattern.length && pattern[i + 1] === '*') {\r\n // ** matches any number of directories\r\n regexStr += '.*';\r\n i += 2;\r\n } else {\r\n // * matches any characters except path separator\r\n regexStr += '[^/]*';\r\n i++;\r\n }\r\n } else if (char === '?') {\r\n regexStr += '[^/]';\r\n i++;\r\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\r\n regexStr += '\\\\' + char;\r\n i++;\r\n } else {\r\n regexStr += char;\r\n i++;\r\n }\r\n }\r\n\r\n regexStr += '$';\r\n\r\n try {\r\n const regex = new RegExp(regexStr, 'i'); // case-insensitive\r\n return regex.test(path);\r\n } catch {\r\n // If regex is invalid, fall back to simple substring match\r\n return path.toLowerCase().includes(pattern.toLowerCase());\r\n }\r\n}\r\n\r\n/**\r\n * Count ignored entries (for filtered metadata)\r\n */\r\nexport function countIgnored(\r\n entries: Array<{ name: string; path?: string }>,\r\n isDir: (entry: { name: string }) => boolean,\r\n ctx: IgnoreContext,\r\n cfg: Configuration\r\n): number {\r\n let count = 0;\r\n for (const entry of entries) {\r\n const relPath = entry.path || entry.name;\r\n const result = shouldIgnore(relPath, isDir(entry), ctx, cfg);\r\n if (result.shouldIgnore) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n}\r\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { ToolError } from '@devicelink-workspace/domain';\n\n/**\n * Normalize a user-provided relative path into POSIX-style (forward slashes),\n * and reject obvious bad inputs early.\n */\nexport function normalizeRelPath(input: string): string {\n const raw = (input ?? '').trim();\n if (!raw) return '.';\n\n // Block null bytes\n if (raw.includes('\\0')) {\n throw toolErr('INVALID_INPUT', 'Path contains null byte.');\n }\n\n // Block absolute paths (POSIX)\n if (raw.startsWith('/')) {\n throw toolErr('PATH_ESCAPE', 'Absolute paths are not allowed. Use a path relative to the root.', {\n hint: 'Use relative paths like \"src/file.ts\" or \".\" for the root directory. Paths must be relative to the configured root.',\n });\n }\n\n // Block Windows absolute paths: C:\\ or C:/, \\\\server\\share\n if (/^[a-zA-Z]:[\\\\/]/.test(raw) || raw.startsWith('\\\\\\\\') || raw.startsWith('//')) {\n throw toolErr('PATH_ESCAPE', 'Absolute/drive/UNC paths are not allowed. Use a path relative to the root.', {\n hint: 'Use relative paths like \"src/file.ts\" or \".\" for the root directory. Do not use drive letters (C:) or UNC paths (\\\\\\\\server).',\n });\n }\n\n // Normalize slashes to POSIX\n const posixish = raw.replace(/\\\\/g, '/');\n\n // Normalize '.' and '..' segments safely\n const norm = path.posix.normalize(posixish);\n\n // Disallow escaping root via '..'\n // norm can be \"..\" or start with \"../\" if it escapes\n if (norm === '..' || norm.startsWith('../')) {\n throw toolErr('PATH_ESCAPE', 'Path escapes the root.', {\n hint: 'Paths cannot use \"..\" to escape the configured root directory. Use paths relative to the root, like \"src/file.ts\" or \"subdir/file.ts\".',\n });\n }\n\n // Disallow weird URL-ish schema tricks\n if (/^[a-zA-Z]+:\\/\\//.test(norm)) {\n throw toolErr('INVALID_INPUT', 'URL-style paths are not allowed.', {\n hint: 'Paths cannot use URL schemes (like \"http://\" or \"file://\"). Use simple relative paths like \"src/file.ts\".',\n });\n }\n\n return norm === '' ? '.' : norm;\n}\n\n/**\n * Resolve an input path safely inside a configured root path.\n * Returns absolute target + a normalized relative path (POSIX).\n *\n * IMPORTANT: uses realpath containment checks to prevent symlink/junction escapes.\n */\nexport async function resolveInRoot(\n rootPath: string,\n inputRel: string\n): Promise<{ absTarget: string; rel: string }> {\n const rel = normalizeRelPath(inputRel);\n\n // Resolve root first\n const absRoot = path.resolve(rootPath);\n const realRoot = await fs.realpath(absRoot);\n\n // Construct candidate under root (syntactic)\n const candidate = path.resolve(realRoot, rel === '.' ? '' : rel);\n\n // Quick containment check (syntactic)\n const relToRoot = path.relative(realRoot, candidate);\n if (relToRoot.startsWith('..') || path.isAbsolute(relToRoot)) {\n throw toolErr('PATH_ESCAPE', 'Path escapes the root.', {\n hint: 'The resolved path escapes the configured root directory. Ensure the path stays within the root boundaries.',\n });\n }\n\n // Symlink/junction protection (semantic)\n // If candidate exists, realpath resolves through symlinks/junctions.\n try {\n const realCandidate = await fs.realpath(candidate);\n const rel2 = path.relative(realRoot, realCandidate);\n if (rel2.startsWith('..') || path.isAbsolute(rel2)) {\n throw toolErr('PATH_ESCAPE', 'Symlink/junction escape detected.', {\n hint: 'A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries.',\n });\n }\n return { absTarget: realCandidate, rel };\n } catch (e: any) {\n // For non-existent targets, we can still be safe by resolving the nearest existing parent.\n if (e?.code !== 'ENOENT') throw e;\n\n const parts = rel.split('/').filter(Boolean);\n for (let i = parts.length; i > 0; i--) {\n const parentRel = parts.slice(0, i).join('/');\n const restRel = parts.slice(i).join('/');\n\n const parentCandidate = path.resolve(realRoot, parentRel);\n try {\n const realParent = await fs.realpath(parentCandidate);\n const relParent = path.relative(realRoot, realParent);\n if (relParent.startsWith('..') || path.isAbsolute(relParent)) {\n throw toolErr('PATH_ESCAPE', 'Symlink/junction escape detected.', {\n hint: 'A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries.',\n });\n }\n return { absTarget: restRel ? path.join(realParent, restRel) : realParent, rel };\n } catch (err: any) {\n if (err?.code === 'ENOENT') continue;\n throw err;\n }\n }\n\n // Nothing exists; treat as not found (and still safe)\n throw toolErr('NOT_FOUND', 'Path not found.', {\n hint: 'The specified path does not exist. Verify the path is correct and that the file or directory exists within the configured root.',\n });\n }\n}\n\n/**\n * Consistent context injection (always use normalized rel path).\n */\nexport function makeContext(args: {\n workspace_id?: string;\n device_id?: string;\n directory_id: string;\n path: string;\n}): { directory_id: string; workspace_id?: string; device_id?: string; path: string } {\n return {\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: args.directory_id,\n path: normalizeRelPath(args.path),\n };\n}\n\n/**\n * Map node fs errors to stable tool errors.\n */\nexport function mapFsError(e: any, fallbackMessage: string): ToolError {\n const code = String(e?.code ?? '');\n\n if (code === 'ENOENT') return toolError('NOT_FOUND', 'Path not found.', { fs_code: code });\n if (code === 'ENOTDIR') return toolError('NOT_A_DIRECTORY', 'Path is not a directory.', { fs_code: code });\n if (code === 'EISDIR') return toolError('NOT_A_FILE', 'Path is a directory, not a file.', { fs_code: code });\n if (code === 'EACCES' || code === 'EPERM')\n return toolError('PERMISSION_DENIED', 'Permission denied.', { fs_code: code });\n\n return toolError('INTERNAL', fallbackMessage, { fs_code: code });\n}\n\n/**\n * A tiny helper to throw ToolError as an exception (if you still use throws internally).\n * You can also return these instead once you convert handlers to ToolResult<> envelopes.\n */\nexport function toolErr(code: string, message: string, details?: Record<string, unknown>): ToolError {\n return toolError(code, message, details);\n}\n\nexport function toolError(code: string, message: string, details?: Record<string, unknown>): ToolError {\n return { code, message, details };\n}\n\n/**\n * Optional: validate directory_id quickly.\n * Tries to match by ID first, then falls back to single directory if available.\n * This handles cases where the directory_id from the resolver might not exactly match\n * the agent's configured directory ID (e.g., if agent was restarted with different directory config).\n */\nexport function requireDirectory(cfg: Configuration, directory_id: string) {\n if (Array.isArray(cfg.directories) && cfg.directories.length === 0) {\n throw toolErr('UNKNOWN_DIRECTORY', `No directories configured.`, {\n hint: `No directories configured. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,\n requested_directory_id: directory_id,\n available_directory_ids: cfg.directories.map(r => r.id),\n available_paths: cfg.directories.map(r => r.path),\n directory_count: cfg.directories.length,\n });\n }\n // First try exact ID match\n let directory = cfg.directories.find((r) => r.id === directory_id);\n \n // If not found and there's only one directory configured, use it as fallback\n // This handles the common case where the agent was restarted and the directory ID changed\n // but there's still only one directory configured\n if (!directory && cfg.directories.length === 1) {\n directory = cfg.directories[0];\n // Note: We don't log here because this function is called frequently and logging\n // should be done at a higher level if needed. The mismatch will be visible in errors.\n }\n \n if (!directory) {\n const availableIds = cfg.directories.map(r => r.id).join(', ') || 'none';\n const availablePaths = cfg.directories.map(r => r.path).join(', ') || 'none';\n const directoryIdStr = directory_id === undefined ? 'undefined (missing)' : String(directory_id);\n throw toolErr('UNKNOWN_DIRECTORY', `Unknown directory_id: ${directoryIdStr}`, {\n hint: `The directory_id \"${directoryIdStr}\" does not match any configured directory. Available directory IDs: ${availableIds}. Available paths: ${availablePaths}. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,\n requested_directory_id: directory_id,\n available_directory_ids: cfg.directories.map(r => r.id),\n available_paths: cfg.directories.map(r => r.path),\n directory_count: cfg.directories.length,\n });\n }\n return directory;\n}\n\n/**\n * Optional: type check helpers (avoid TOCTOU where possible)\n */\nexport async function statOrMap(absPath: string) {\n try {\n return await fs.stat(absPath);\n } catch (e) {\n throw mapFsError(e, 'Failed to stat path.');\n }\n}\n", "/**\n * Audit logging for filesystem operations\n * This can be extended later to integrate with the CLI logger system\n */\n\nexport type FsAuditOperation = 'read' | 'read_many' | 'list' | 'tree' | 'info' | 'grep' | 'search';\n\nexport type FsAuditEntry = {\n operation: FsAuditOperation;\n path: string; // relative path (sanitized)\n directory_id: string;\n workspace_id?: string;\n device_id?: string;\n success: boolean;\n error?: string;\n metadata?: {\n file_count?: number;\n match_count?: number;\n bytes_read?: number;\n };\n timestamp: number;\n};\n\n/**\n * Log filesystem operations for audit trail.\n * This provides security monitoring and compliance tracking.\n */\nexport function auditFsOperation(\n operation: FsAuditOperation,\n context: { directory_id: string; workspace_id?: string; device_id?: string; path: string },\n success: boolean,\n error?: string,\n metadata?: FsAuditEntry['metadata']\n): void {\n const entry: FsAuditEntry = {\n operation,\n path: context.path || '.',\n directory_id: context.directory_id,\n workspace_id: context.workspace_id,\n device_id: context.device_id,\n success,\n error: error ? error.substring(0, 200) : undefined, // Truncate long errors\n metadata,\n timestamp: Date.now(),\n };\n\n // Log as structured audit entry\n // TODO: Integrate with CLI logger system when available\n const logMsg = `[FS_AUDIT] ${operation} ${success ? 'SUCCESS' : 'FAILED'} directory=${entry.directory_id} path=${entry.path}${entry.workspace_id ? ` workspace=${entry.workspace_id}` : ''}${entry.device_id ? ` device=${entry.device_id}` : ''}${entry.error ? ` error=${entry.error}` : ''}${metadata ? ` ${JSON.stringify(metadata)}` : ''}`;\n \n // For now, audit operations are logged to console\n // This can be extended to use the CLI logger system\n // if (success) {\n // console.log(logMsg);\n // } else {\n // console.warn(logMsg);\n // }\n}\n", "import fs from 'node:fs/promises';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsReadOutput, FsReadArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { shouldIgnore } from '../util/ignore.js';\n\n/**\n * Executer for fs_read tool\n */\nexport class FsReadExecuter extends BaseExecuter<FsReadArgs, FsReadOutput> {\n protected async executeTool(args: FsReadArgs): Promise<FsReadOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget: absPath, rel } = await resolveInRoot(directory.path, args.path);\n\n // Check denylist and ignore rules\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n const ignoreResult = shouldIgnore(rel, false, ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`);\n throw toolErr('PERMISSION_DENIED', `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`, {\n path: rel,\n reason: ignoreResult.reason,\n });\n }\n\n const offset = Math.max(args.offset ?? 0, 0);\n const limit = Math.min(Math.max(args.limit ?? 40000, 1), 200000);\n const encoding = args.encoding ?? 'utf-8';\n\n // Check that target is a file\n let st;\n try {\n st = await fs.stat(absPath);\n } catch (e) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, mapFsError(e, 'Failed to stat file.').message);\n throw mapFsError(e, 'Failed to stat file.');\n }\n if (!st.isFile()) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, 'Path is not a file.');\n throw toolErr('NOT_A_FILE', 'Path is not a file.', {\n path: rel,\n hint: 'The path must point to a file, not a directory. Use fs_list or fs_tree to explore directories, or provide a file path to read.',\n });\n }\n\n let fh;\n try {\n fh = await fs.open(absPath, 'r');\n } catch (e) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, mapFsError(e, 'Failed to open file.').message);\n throw mapFsError(e, 'Failed to open file.');\n }\n\n try {\n const buf = Buffer.alloc(limit);\n const { bytesRead } = await fh.read(buf, 0, limit, offset);\n\n const slice = buf.subarray(0, bytesRead);\n const content = slice.toString(encoding as BufferEncoding);\n\n const next_offset = offset + bytesRead;\n const eof = bytesRead < limit;\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful read\n auditFsOperation('read', context, true, undefined, {\n bytes_read: bytesRead,\n });\n\n return {\n content,\n bytes_read: bytesRead,\n next_offset,\n eof,\n context,\n };\n } catch (e: any) {\n // Audit failed read\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, e?.message || String(e));\n throw e;\n } finally {\n await fh.close();\n }\n }\n}\n\n/**\n * Convenience function to execute fs_read tool\n */\nexport async function executeFsRead(\n config: Configuration,\n args: FsReadArgs\n): Promise<ToolResult<FsReadOutput>> {\n const executer = new FsReadExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsInfoOutput, FsInfoArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Executer for fs_info tool\n */\nexport class FsInfoExecuter extends BaseExecuter<FsInfoArgs, FsInfoOutput> {\n protected async executeTool(args: FsInfoArgs): Promise<FsInfoOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget: absPath, rel } = await resolveInRoot(directory.path, args.path);\n\n // Check if it's a symlink first\n let isSymlink = false;\n let target: string | undefined;\n\n try {\n target = await fs.readlink(absPath);\n isSymlink = true;\n } catch (e: any) {\n // Ignore if not a symlink; but if path missing, surface NOT_FOUND\n if (e?.code === 'ENOENT') throw mapFsError(e, 'Path not found.');\n }\n\n // Get stat information\n let stat;\n try {\n stat = isSymlink ? await fs.stat(absPath) : await fs.lstat(absPath);\n } catch (e) {\n throw mapFsError(e, 'Failed to stat path.');\n }\n\n // Determine type\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (stat.isDirectory()) {\n type = 'dir';\n } else if (stat.isFile()) {\n type = 'file';\n } else if (isSymlink) {\n type = 'symlink';\n }\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful info operation\n auditFsOperation('info', context, true);\n\n return {\n type,\n size: stat.isFile() ? stat.size : undefined,\n mtime: Math.floor(stat.mtimeMs / 1000),\n ctime: Math.floor(stat.ctimeMs / 1000),\n atime: Math.floor(stat.atimeMs / 1000),\n is_symlink: isSymlink,\n target: isSymlink ? target : undefined,\n context,\n };\n }\n}\n\n/**\n * Convenience function to execute fs_info tool\n */\nexport async function executeFsInfo(\n config: Configuration,\n args: FsInfoArgs\n): Promise<ToolResult<FsInfoOutput>> {\n const executer = new FsInfoExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport type { Dirent } from 'node:fs';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsTreeNode, FsTreeOutput, FsSummary, FsTreeDisplayRow, ToolError, FsTreeArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { FsGrepExecuter, type FsGrepArgs } from './fs-grep.js';\nimport { FsReadManyExecuter, type FsReadManyArgs } from './fs-read-many.js';\n\nfunction collectFilePaths(node: FsTreeNode, out: string[], limit: number) {\n if (out.length >= limit) return;\n if (node.type === 'file') {\n out.push(node.path);\n return;\n }\n if (node.children) {\n for (const c of node.children) {\n if (out.length >= limit) break;\n collectFilePaths(c, out, limit);\n }\n }\n}\n\n/**\n * Deterministic ranking function that sorts files by importance buckets.\n * Returns paths sorted by: docs > config > ci > source > other\n */\nfunction rankImportant(paths: string[]): string[] {\n const getBucket = (p: string): number => {\n const x = p.toLowerCase();\n const parts = x.split('/');\n \n // Top priority: documentation files\n if (x === 'readme.md' || x.endsWith('/readme.md') || x.includes('/readme.md')) return 0;\n if (x.endsWith('.md')) return 1;\n \n // High priority: config files\n if (x.endsWith('package.json') || x.endsWith('pyproject.toml') || x.endsWith('go.mod') || \n x.endsWith('cargo.toml') || x.endsWith('pom.xml') || x.endsWith('build.gradle')) return 2;\n if (x.includes('dockerfile') || x.includes('compose') || x.endsWith('.env.example')) return 3;\n \n // Config directories\n if (parts.includes('config') || parts.includes('conf') || parts.includes('settings')) return 4;\n \n // CI/CD\n if (parts.includes('ci') || parts.includes('.github') || parts.includes('.gitlab') || \n parts.includes('jenkins') || x.includes('workflow')) return 5;\n \n // Source code (lower priority to avoid noise)\n if (x.endsWith('.ts') || x.endsWith('.tsx') || x.endsWith('.js') || x.endsWith('.jsx') ||\n x.endsWith('.py') || x.endsWith('.go') || x.endsWith('.rs') || x.endsWith('.java')) return 6;\n \n // Other\n return 7;\n };\n \n return [...paths].sort((a, b) => {\n const bucketA = getBucket(a);\n const bucketB = getBucket(b);\n if (bucketA !== bucketB) return bucketA - bucketB;\n // Within same bucket, sort alphabetically\n return a.localeCompare(b);\n });\n}\n\n/**\n * Flatten tree into display rows with depth information\n */\nfunction flattenTreeToRows(node: FsTreeNode, depth: number, rows: FsTreeDisplayRow[], errorMap?: Map<string, { code: string; message: string }>): void {\n const row: FsTreeDisplayRow = {\n path: node.path,\n name: node.name,\n type: node.type,\n depth,\n size: node.size,\n mtime: node.mtime,\n ext: node.ext,\n hidden: node.hidden,\n ignored: node.ignored,\n };\n \n // Check if this node has an associated error\n if (errorMap?.has(node.path)) {\n row.error = errorMap.get(node.path);\n } else if (node.type === 'other' && node.name === '<readdir_error>') {\n row.error = {\n code: 'INTERNAL',\n message: 'Failed to read directory',\n };\n }\n \n rows.push(row);\n \n if (node.children) {\n for (const child of node.children) {\n flattenTreeToRows(child, depth + 1, rows, errorMap);\n }\n }\n}\n\nasync function buildTree(\n absPath: string,\n relPath: string,\n depth: number,\n maxDepth: number,\n only: 'all' | 'files' | 'dirs',\n includeHidden: boolean,\n maxEntries: number,\n currentCount: { value: number },\n ignoredCount: { value: number },\n summary: FsSummary,\n extCounts: Map<string, number>,\n detail: 'basic' | 'stat' | 'digest',\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration,\n truncated: { reason?: 'MAX_ENTRIES' | 'MAX_DEPTH' },\n errorMap?: Map<string, { code: string; message: string }>\n): Promise<FsTreeNode | null> {\n if (currentCount.value >= maxEntries) {\n truncated.reason = 'MAX_ENTRIES';\n return null;\n }\n\n if (depth > maxDepth) {\n truncated.reason = 'MAX_DEPTH';\n return null;\n }\n\n const entryRel = relPath === '.' ? '.' : relPath.replace(/\\\\/g, '/');\n let stat;\n \n try {\n stat = await fs.lstat(absPath);\n } catch (e: any) {\n // Non-fatal: create error node instead of throwing\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n summary.total_entries++;\n \n const node: FsTreeNode = {\n name: path.basename(relPath) || relPath,\n type: 'other',\n path: entryRel,\n hidden: path.basename(relPath)?.startsWith('.'),\n ignored: false,\n };\n \n // Store error for display rows\n if (errorMap) {\n errorMap.set(entryRel, {\n code: errorCode,\n message: `Failed to stat: ${errorMessage}`,\n });\n }\n \n if (only === 'files' || only === 'dirs') return null;\n currentCount.value++;\n return node;\n }\n\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (stat.isDirectory()) type = 'dir';\n else if (stat.isFile()) type = 'file';\n else if (stat.isSymbolicLink()) type = 'symlink';\n\n const ignoreResult = shouldIgnore(entryRel, stat.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n summary.ignored++;\n return null;\n }\n\n summary.total_entries++;\n if (type === 'file') summary.files++;\n else if (type === 'dir') summary.dirs++;\n else if (type === 'symlink') summary.symlinks++;\n\n const isHidden = path.basename(relPath)?.startsWith('.');\n if (isHidden) summary.hidden++;\n\n const ext = type === 'file' ? path.extname(path.basename(relPath) || relPath).slice(1) : undefined;\n if (ext && (detail === 'stat' || detail === 'digest')) {\n extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n if (type === 'file' && (detail === 'stat' || detail === 'digest')) {\n summary.total_file_bytes = (summary.total_file_bytes ?? 0) + (stat.size ?? 0);\n }\n\n const node: FsTreeNode = {\n name: path.basename(relPath) || relPath,\n type,\n path: entryRel,\n size: (detail === 'stat' || detail === 'digest') && stat.isFile() ? stat.size : undefined,\n mtime: (detail === 'stat' || detail === 'digest') ? Math.floor(stat.mtimeMs / 1000) : undefined,\n ext,\n hidden: isHidden,\n ignored: false,\n };\n\n if (only === 'files' && type !== 'file' && type !== 'symlink') return null;\n if (only === 'dirs' && type !== 'dir') return null;\n\n currentCount.value++;\n\n if (type === 'dir' && depth < maxDepth) {\n let entries: Dirent[];\n let readdirError: { code: string; message: string } | undefined;\n \n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch (e: any) {\n // Non-fatal: log error but continue with empty children\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n readdirError = {\n code: errorCode,\n message: errorMessage,\n };\n entries = [];\n }\n\n const filtered = includeHidden ? entries : entries.filter((e: Dirent) => !e.name.startsWith('.'));\n\n filtered.sort((a: Dirent, b: Dirent) => {\n const aIsDir = a.isDirectory() ? 0 : 1;\n const bIsDir = b.isDirectory() ? 0 : 1;\n if (aIsDir !== bIsDir) return aIsDir - bIsDir;\n return a.name.localeCompare(b.name);\n });\n\n const children: FsTreeNode[] = [];\n\n // If readdir failed, store error for display rows\n if (readdirError && errorMap) {\n errorMap.set(entryRel, {\n code: readdirError.code,\n message: `Failed to read directory: ${readdirError.message}`,\n });\n }\n\n for (const entry of filtered) {\n if (currentCount.value >= maxEntries) break;\n\n const childAbs = path.join(absPath, entry.name);\n const childRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n const childRel = childRelPath.replace(/\\\\/g, '/');\n\n const preIgnore = shouldIgnore(childRel, entry.isDirectory(), ignoreCtx, cfg);\n if (preIgnore.shouldIgnore) {\n ignoredCount.value++;\n summary.ignored++;\n continue;\n }\n\n try {\n const child = await buildTree(\n childAbs,\n childRelPath,\n depth + 1,\n maxDepth,\n only,\n includeHidden,\n maxEntries,\n currentCount,\n ignoredCount,\n summary,\n extCounts,\n detail,\n ignoreCtx,\n cfg,\n truncated,\n errorMap\n );\n\n if (child) children.push(child);\n } catch (e: any) {\n // Non-fatal: log error for this path but continue with other entries\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n \n // Store error for display rows\n if (errorMap) {\n errorMap.set(childRel, {\n code: errorCode,\n message: `Failed to build subtree: ${errorMessage}`,\n });\n }\n \n // Create an error node to indicate this subtree failed\n summary.total_entries++;\n const errorNode: FsTreeNode = {\n name: path.basename(childRelPath) || childRelPath,\n type: 'other',\n path: childRel,\n hidden: path.basename(childRelPath)?.startsWith('.'),\n ignored: false,\n };\n \n if (only === 'files' || only === 'dirs') {\n // Skip error nodes if filtering by type\n continue;\n }\n \n currentCount.value++;\n children.push(errorNode);\n }\n }\n\n if (children.length > 0) node.children = children;\n }\n\n return node;\n}\n\n/**\n * Executer for fs_tree tool\n */\nexport class FsTreeExecuter extends BaseExecuter<FsTreeArgs, FsTreeOutput> {\n protected async executeTool(args: FsTreeArgs): Promise<FsTreeOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path);\n\n const maxDepth = Math.min(Math.max(args.max_depth ?? 3, 1), 20);\n const only = args.only ?? 'all';\n const includeHidden = args.include_hidden ?? false;\n const maxEntries = Math.min(Math.max(args.max_entries ?? 5000, 1), 20000);\n const detail = args.detail ?? 'stat';\n const includeDisplay = args.include_display ?? false;\n const maxDisplayRows = Math.min(Math.max(args.max_display_rows ?? 2000, 1), 20000);\n\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n throw toolErr('NOT_A_DIRECTORY', 'Path is not a directory.', {\n path: rel,\n hint: 'The path must point to a directory to build a tree. Provide a directory path, not a file.',\n });\n }\n } catch (e: any) {\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to build tree.');\n }\n\n const ignoreCtx = { directory_id: directoryId, workspace_id: args.workspace_id, directory_path: directory.path };\n\n const truncated = { reason: undefined as 'MAX_ENTRIES' | 'MAX_DEPTH' | undefined };\n const currentCount = { value: 0 };\n const ignoredCount = { value: 0 };\n const summary: FsSummary = {\n total_entries: 0,\n files: 0,\n dirs: 0,\n symlinks: 0,\n hidden: 0,\n ignored: 0,\n total_file_bytes: 0,\n };\n const extCounts = new Map<string, number>();\n const errorMap = new Map<string, { code: string; message: string }>(); // Track errors by path\n\n const tree = await buildTree(\n absTarget,\n rel,\n 0,\n maxDepth,\n only,\n includeHidden,\n maxEntries,\n currentCount,\n ignoredCount,\n summary,\n extCounts,\n detail,\n ignoreCtx,\n this.config,\n truncated,\n errorMap\n );\n\n if (!tree) throw toolErr('INTERNAL', 'Failed to build tree (empty result).');\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n if (detail === 'digest' && extCounts.size > 0) {\n summary.by_ext = Array.from(extCounts.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n }\n\n const result: FsTreeOutput = {\n tree,\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n\n // Only include display rows when explicitly requested to keep payload small.\n if (includeDisplay) {\n const displayRows: FsTreeDisplayRow[] = [];\n flattenTreeToRows(tree, 0, displayRows, errorMap);\n if (displayRows.length > maxDisplayRows) {\n displayRows.length = maxDisplayRows;\n // If we truncated display rows, reflect truncation for callers.\n result.truncated = result.truncated ?? {\n reason: 'MAX_ENTRIES',\n continuation: 'Display rows truncated; reduce max_entries/max_depth or lower max_display_rows',\n };\n }\n result.display = { rows: displayRows };\n }\n\n if (truncated.reason) {\n result.truncated = {\n reason: truncated.reason,\n continuation:\n truncated.reason === 'MAX_ENTRIES'\n ? 'Reduce max_entries or list this folder with fs_list instead'\n : 'Reduce max_depth or list this folder with fs_list instead',\n };\n }\n\n // summary rules\n if (detail === 'digest' || args.include_summary) {\n result.summary = summary;\n }\n\n // extras\n const extras: FsTreeOutput['extras'] = {};\n\n if (args.grep?.query) {\n try {\n const grepExecuter = new FsGrepExecuter(this.config);\n const grepArgs: FsGrepArgs = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n path: args.path ?? '.',\n query: args.grep.query,\n mode: args.grep.mode ?? 'substring',\n file_glob: args.grep.file_glob,\n max_files: args.grep.max_files ?? 2000,\n max_matches: args.grep.max_matches ?? 200,\n context_lines: args.grep.context_lines ?? 2,\n case_sensitive: args.grep.case_sensitive ?? false,\n };\n const grepResult = await grepExecuter.execute(grepArgs);\n \n if (grepResult.ok) {\n extras.grep = {\n matches: grepResult.data.matches,\n meta: grepResult.data.meta,\n context: grepResult.data.context,\n };\n }\n } catch (e: any) {\n // Non-fatal: if grep fails, just skip it\n // Tree result is still valid without grep extras\n }\n }\n\n const explicit = args.read?.paths?.filter(Boolean) ?? [];\n let auto: string[] = [];\n\n if (args.read?.auto) {\n const maxFiles = Math.min(Math.max(args.read.auto.max_files ?? 10, 1), 50);\n const collected: string[] = [];\n collectFilePaths(tree, collected, 3000);\n auto = rankImportant(collected).slice(0, maxFiles);\n }\n\n const merged = Array.from(new Set([...explicit, ...auto])).slice(0, 50);\n\n if (merged.length > 0) {\n try {\n const limitEach = Math.min(Math.max(args.read?.auto?.max_bytes_each ?? 20000, 1), 200000);\n const readManyExecuter = new FsReadManyExecuter(this.config);\n const readManyArgs: FsReadManyArgs = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n default_limit: limitEach,\n default_encoding: 'utf-8',\n items: merged.map((p) => ({ path: p })),\n };\n const readResult = await readManyExecuter.execute(readManyArgs);\n \n if (readResult.ok) {\n extras.read_many = {\n files: readResult.data.files.map((f) => ({\n path: f.path,\n content: f.content,\n bytes_read: f.bytes_read,\n truncated: f.truncated,\n error: f.error,\n })),\n context: readResult.data.context,\n };\n }\n } catch (e: any) {\n // Non-fatal: if read_many fails, just skip it\n // Tree result is still valid without read_many extras\n }\n }\n\n if (Object.keys(extras).length > 0) {\n result.extras = extras;\n }\n\n // Audit successful tree operation\n auditFsOperation('tree', context, true, undefined, {\n file_count: currentCount.value,\n });\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_tree tool\n */\nexport async function executeFsTree(\n config: Configuration,\n args: FsTreeArgs\n): Promise<ToolResult<FsTreeOutput>> {\n const executer = new FsTreeExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsGrepArgs, FsGrepOutput, FsGrepMatch } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Simple glob pattern matcher for file paths\n */\nfunction matchesFileGlob(relPath: string, fileGlob: string): boolean {\n // Convert glob to regex\n let regexStr = '^';\n let i = 0;\n while (i < fileGlob.length) {\n const char = fileGlob[i];\n if (char === '*') {\n if (i + 1 < fileGlob.length && fileGlob[i + 1] === '*') {\n regexStr += '.*';\n i += 2;\n } else {\n regexStr += '[^/]*';\n i++;\n }\n } else if (char === '?') {\n regexStr += '[^/]';\n i++;\n } else if (char === '{') {\n // Handle {ts,js,md} patterns\n const end = fileGlob.indexOf('}', i);\n if (end === -1) {\n regexStr += '\\\\{';\n i++;\n } else {\n const alternatives = fileGlob.substring(i + 1, end).split(',');\n regexStr += '(' + alternatives.map((alt) => alt.trim().replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|') + ')';\n i = end + 1;\n }\n } else if ('\\\\^$|.+()[]'.includes(char!)) {\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i');\n return regex.test(relPath);\n } catch {\n return false;\n }\n}\n\nasync function searchInFile(\n absPath: string,\n relPath: string,\n query: string,\n mode: 'substring' | 'regex',\n caseSensitive: boolean,\n contextLines: number,\n maxMatches: number,\n matches: FsGrepMatch[]\n): Promise<number> {\n let content: string;\n try {\n content = await fs.readFile(absPath, 'utf-8');\n } catch {\n // Skip files we can't read\n return 0;\n }\n\n const lines = content.split(/\\r?\\n/);\n let found = 0;\n\n let regex: RegExp;\n if (mode === 'regex') {\n try {\n regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n } catch {\n // Invalid regex, fall back to substring\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n regex = new RegExp(escaped, caseSensitive ? 'g' : 'gi');\n }\n } else {\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n regex = new RegExp(escaped, caseSensitive ? 'g' : 'gi');\n }\n\n for (let i = 0; i < lines.length && found < maxMatches; i++) {\n const line = lines[i]!;\n if (regex.test(line)) {\n // Reset regex lastIndex for next iteration\n regex.lastIndex = 0;\n\n const startLine = Math.max(0, i - contextLines);\n const endLine = Math.min(lines.length - 1, i + contextLines);\n const snippet = lines.slice(startLine, endLine + 1);\n\n matches.push({\n path: relPath,\n line: i + 1, // 1-indexed\n preview: line.trim(),\n snippet,\n });\n found++;\n }\n }\n\n return found;\n}\n\nasync function grepDirectory(\n absPath: string,\n relPath: string,\n rootPath: string,\n query: string,\n mode: 'substring' | 'regex',\n fileGlob: string | undefined,\n caseSensitive: boolean,\n contextLines: number,\n maxFiles: number,\n maxMatches: number,\n filesScanned: { value: number },\n matches: FsGrepMatch[],\n ignoredCount: { value: number },\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration\n): Promise<void> {\n if (filesScanned.value >= maxFiles || matches.length >= maxMatches) {\n return;\n }\n\n let entries;\n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch {\n // Skip directories we can't read\n return;\n }\n\n for (const entry of entries) {\n if (filesScanned.value >= maxFiles || matches.length >= maxMatches) break;\n\n const entryAbsPath = path.join(absPath, entry.name);\n const entryRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, entry.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n // Never recurse into ignored directories\n continue;\n }\n\n if (entry.isFile()) {\n // Check file_glob filter\n if (fileGlob && !matchesFileGlob(entryRelPath, fileGlob)) {\n continue;\n }\n\n filesScanned.value++;\n await searchInFile(entryAbsPath, entryRelPath, query, mode, caseSensitive, contextLines, maxMatches - matches.length, matches);\n } else if (entry.isDirectory()) {\n // Recurse into directories\n await grepDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n fileGlob,\n caseSensitive,\n contextLines,\n maxFiles,\n maxMatches,\n filesScanned,\n matches,\n ignoredCount,\n ignoreCtx,\n cfg\n );\n }\n }\n}\n\n/**\n * Executer for fs_grep tool\n */\nexport class FsGrepExecuter extends BaseExecuter<FsGrepArgs, FsGrepOutput> {\n protected async executeTool(args: FsGrepArgs): Promise<FsGrepOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n\n const query = args.query;\n if (!query || query.length === 0) {\n throw toolErr('INVALID_INPUT', 'Query is required.', {\n hint: 'Query should be a search pattern to find in file contents. Use a substring (default) or regex pattern (with mode=\"regex\"). Examples: \"function\", \"import.*from\", \"TODO\"',\n });\n }\n\n const mode = args.mode ?? 'substring';\n const fileGlob = args.file_glob;\n const maxFiles = Math.min(Math.max(args.max_files ?? 2000, 1), 10000);\n const maxMatches = Math.min(Math.max(args.max_matches ?? 200, 1), 1000);\n const contextLines = Math.min(Math.max(args.context_lines ?? 2, 0), 10);\n const caseSensitive = args.case_sensitive ?? false;\n\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path ?? '.');\n\n // Check that starting path is a directory (if provided and not \".\")\n if (rel !== '.') {\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n throw toolErr('NOT_A_DIRECTORY', 'Grep path is not a directory.', {\n path: rel,\n hint: 'The grep path must be a directory. Grep searches within directories recursively. Use \".\" to search from the root, or provide a directory path.',\n });\n }\n } catch (e: any) {\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to stat grep path.');\n }\n }\n\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const matches: FsGrepMatch[] = [];\n const filesScanned = { value: 0 };\n const ignoredCount = { value: 0 };\n\n await grepDirectory(absTarget, rel, directory.path, query, mode, fileGlob, caseSensitive, contextLines, maxFiles, maxMatches, filesScanned, matches, ignoredCount, ignoreCtx, this.config);\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful grep operation\n auditFsOperation('grep', context, true, undefined, {\n file_count: filesScanned.value,\n match_count: matches.length,\n });\n\n return {\n matches,\n meta: {\n files_scanned: filesScanned.value,\n matches: matches.length,\n truncated: filesScanned.value >= maxFiles || matches.length >= maxMatches,\n },\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n }\n}\n\n/**\n * Convenience function to execute fs_grep tool\n */\nexport async function executeFsGrep(\n config: Configuration,\n args: FsGrepArgs\n): Promise<ToolResult<FsGrepOutput>> {\n const executer = new FsGrepExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\nimport type { ToolResult, ToolError, FsReadManyArgs, FsReadManyOutput, FsReadManyItem } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, makeContext, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { FsReadExecuter } from './fs-read.js';\nimport type { FsReadArgs } from '@devicelink-workspace/domain';\nimport isEmpty from 'lodash/isEmpty.js';\nimport { shouldIgnore } from '../util/ignore.js';\n\n/**\n * Executer for fs_read_many tool\n */\nexport class FsReadManyExecuter extends BaseExecuter<FsReadManyArgs, FsReadManyOutput> {\n protected async executeTool(args: FsReadManyArgs): Promise<FsReadManyOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const defaultLimit = args.default_limit ?? 12000;\n const defaultEncoding = args.default_encoding ?? 'utf-8';\n\n // Normalize input: accept either items[] or paths[]\n let normalizedItems: FsReadManyItem[] = [];\n \n if (args.items && Array.isArray(args.items)) {\n normalizedItems = args.items;\n }\n\n if (isEmpty(normalizedItems)) {\n throw toolErr(\n 'INVALID_INPUT',\n 'fs_read_many expects { items: [{path,...}] }',\n {\n receivedKeys: Object.keys(args ?? {}),\n hint: 'Provide an \"items\" array with at least one object containing a \"path\" property. Each item can optionally include \"offset\", \"limit\", and \"encoding\". Example: { items: [{ path: \"file1.ts\" }, { path: \"file2.ts\", limit: 5000 }] }',\n }\n );\n }\n\n const files: FsReadManyOutput['files'] = [];\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const readExecuter = new FsReadExecuter(this.config);\n\n for (const item of normalizedItems) {\n try {\n // Check denylist and ignore rules before attempting read\n const ignoreResult = shouldIgnore(item.path, false, ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: 'PERMISSION_DENIED',\n message: `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`,\n },\n });\n continue;\n }\n\n const readArgs: FsReadArgs = {\n directory_id: directoryId,\n path: item.path,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n offset: item.offset ?? 0,\n limit: item.limit ?? defaultLimit,\n encoding: item.encoding ?? defaultEncoding,\n };\n\n const result = await readExecuter.execute(readArgs);\n \n if (!result.ok) {\n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: result.error.code,\n message: result.error.message,\n },\n });\n continue;\n }\n\n files.push({\n path: item.path,\n content: result.data.content,\n bytes_read: result.data.bytes_read,\n truncated: !result.data.eof,\n });\n } catch (e: any) {\n // Extract structured error from ToolError if available\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e);\n \n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: errorCode,\n message: errorMessage,\n },\n });\n }\n }\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: '.',\n });\n\n auditFsOperation('read_many', context, true, undefined, {\n file_count: files.length,\n });\n\n return {\n files,\n context,\n };\n }\n}\n\n/**\n * Convenience function to execute fs_read_many tool\n */\nexport async function executeFsReadMany(\n config: Configuration,\n args: FsReadManyArgs\n): Promise<ToolResult<FsReadManyOutput>> {\n const executer = new FsReadManyExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsSearchEntry, FsSearchOutput, FsSearchArgs, PaginationMeta, ToolMessage } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Simple glob pattern matcher\n * Supports: *, **, ?, [chars], [!chars]\n * Basic implementation - not as full-featured as minimatch but sufficient for common patterns\n */\nfunction matchesGlob(name: string, pattern: string): boolean {\n // Convert glob pattern to regex\n let regexStr = '^';\n let i = 0;\n while (i < pattern.length) {\n const char = pattern[i];\n if (char === '*') {\n if (i + 1 < pattern.length && pattern[i + 1] === '*') {\n // ** matches any number of directories\n regexStr += '.*';\n i += 2;\n } else {\n // * matches any characters except path separator\n regexStr += '[^/\\\\\\\\]*';\n i++;\n }\n } else if (char === '?') {\n // ? matches any single character except path separator\n regexStr += '[^/\\\\\\\\]';\n i++;\n } else if (char === '[') {\n // Character class\n const end = pattern.indexOf(']', i);\n if (end === -1) {\n regexStr += '\\\\[';\n i++;\n } else {\n const classContent = pattern.substring(i + 1, end);\n if (classContent.startsWith('!')) {\n regexStr += '[^' + classContent.substring(1) + ']';\n } else {\n regexStr += '[' + classContent + ']';\n }\n i = end + 1;\n }\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\n // Escape special regex characters\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i'); // case-insensitive\n return regex.test(name);\n } catch {\n // If regex is invalid, fall back to substring match\n return name.toLowerCase().includes(pattern.toLowerCase());\n }\n}\n\nfunction matchesQuery(name: string, query: string, mode: 'substring' | 'glob'): boolean {\n if (mode === 'glob') {\n return matchesGlob(name, query);\n }\n // substring mode (case-insensitive)\n return name.toLowerCase().includes(query.toLowerCase());\n}\n\n/**\n * Calculate ranking score for search results\n */\nfunction calculateScore(entry: { name: string; path: string }, prefer_paths?: string[], avoid_paths?: string[]): number {\n let score = 100; // base score\n\n // Boost if path matches prefer_paths\n if (prefer_paths) {\n for (const prefer of prefer_paths) {\n if (entry.path.startsWith(prefer)) {\n score += 50;\n break;\n }\n }\n }\n\n // Penalize if path matches avoid_paths\n if (avoid_paths) {\n for (const avoid of avoid_paths) {\n if (entry.path.startsWith(avoid)) {\n score -= 30;\n break;\n }\n }\n }\n\n // Boost exact name matches\n if (entry.name === entry.path.split('/').pop()) {\n score += 20;\n }\n\n return score;\n}\n\n/**\n * Check if path matches file_glob pattern\n */\nfunction matchesFileGlob(relPath: string, fileGlob: string): boolean {\n // Simple glob matching for file patterns\n // Convert glob to regex (similar to matchesGlob but for full paths)\n let regexStr = '^';\n let i = 0;\n while (i < fileGlob.length) {\n const char = fileGlob[i];\n if (char === '*') {\n if (i + 1 < fileGlob.length && fileGlob[i + 1] === '*') {\n regexStr += '.*';\n i += 2;\n } else {\n regexStr += '[^/]*';\n i++;\n }\n } else if (char === '?') {\n regexStr += '[^/]';\n i++;\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i');\n return regex.test(relPath);\n } catch {\n return false;\n }\n}\n\nasync function searchDirectory(\n absPath: string,\n relPath: string,\n rootPath: string,\n query: string,\n mode: 'substring' | 'glob',\n recursive: boolean,\n only: 'all' | 'files' | 'dirs',\n includeHidden: boolean,\n maxResults: number,\n results: FsSearchEntry[],\n ignoredCount: { value: number },\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration,\n fileGlob?: string,\n preferPaths?: string[],\n avoidPaths?: string[],\n includeStats?: boolean\n): Promise<void> {\n if (results.length >= maxResults) {\n return;\n }\n\n let entries;\n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch (e) {\n // If we can't read the directory, skip it\n return;\n }\n\n // Filter hidden files\n const visibleEntries = includeHidden ? entries : entries.filter((e) => !e.name.startsWith('.'));\n\n for (const entry of visibleEntries) {\n if (results.length >= maxResults) break;\n\n const entryAbsPath = path.join(absPath, entry.name);\n const entryRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, entry.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n // Never recurse into ignored directories - skip them entirely\n continue;\n }\n\n // Check file_glob filter\n if (fileGlob && !matchesFileGlob(entryRelPath, fileGlob)) {\n // Still recurse into directories if recursive\n if (recursive && entry.isDirectory()) {\n await searchDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults,\n results,\n ignoredCount,\n ignoreCtx,\n cfg,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n }\n continue;\n }\n\n // Check if name matches query\n const matches = matchesQuery(entry.name, query, mode);\n\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (entry.isDirectory()) type = 'dir';\n else if (entry.isFile()) type = 'file';\n else if (entry.isSymbolicLink()) type = 'symlink';\n\n // Apply filter\n const shouldInclude =\n matches &&\n (only === 'all' || (only === 'files' && (type === 'file' || type === 'symlink')) || (only === 'dirs' && type === 'dir'));\n\n if (shouldInclude) {\n // Get stat for metadata (if includeStats is true or undefined)\n let size: number | undefined;\n let mtime: number | undefined;\n if (includeStats !== false) {\n try {\n const st = await fs.stat(entryAbsPath);\n size = st.isFile() ? st.size : undefined;\n mtime = Math.floor(st.mtimeMs / 1000);\n } catch {\n // Stat failed, continue without size/mtime\n }\n }\n\n const ext = type === 'file' ? path.extname(entry.name).slice(1) : undefined;\n\n // Calculate ranking score\n const score = calculateScore({ name: entry.name, path: entryRelPath }, preferPaths, avoidPaths);\n\n results.push({\n name: entry.name,\n path: entryRelPath,\n type,\n size,\n mtime,\n ext,\n hidden: entry.name.startsWith('.'),\n ignored: false, // already filtered out ignored entries\n score,\n matched: 'name',\n });\n }\n\n // Recurse into directories if recursive is true\n if (recursive && type === 'dir') {\n await searchDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults,\n results,\n ignoredCount,\n ignoreCtx,\n cfg,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n }\n }\n}\n\n/**\n * Executer for fs_search tool\n */\nexport class FsSearchExecuter extends BaseExecuter<FsSearchArgs, FsSearchOutput> {\n protected async executeTool(args: FsSearchArgs): Promise<FsSearchOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n\n const query = args.query;\n if (!query || query.length === 0) {\n throw toolErr('INVALID_INPUT', 'Query is required.', {\n hint: 'Query should be a pattern to match file or directory names. Use a substring (default) or glob pattern (with mode=\"glob\"). Examples: \"config\", \"*.ts\", \"test/**\"',\n });\n }\n\n const mode = args.mode ?? 'substring';\n const recursive = args.recursive ?? true;\n const only = args.only ?? 'all';\n const includeHidden = args.include_hidden ?? false;\n const maxResults = Math.min(Math.max(args.max_results ?? 200, 1), 20000);\n const offset = Math.max(args.offset ?? 0, 0);\n const fileGlob = args.file_glob;\n const preferPaths = args.prefer_paths;\n const avoidPaths = args.avoid_paths;\n const includeStats = args.include_stats !== false; // default true\n\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path ?? '.');\n\n let searchPath = absTarget;\n let searchRelPath = rel;\n const messages: ToolMessage[] = [];\n\n // Check that starting path is a directory (if provided and not \".\")\n if (rel !== '.') {\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n // If it's a file, search the directory containing it\n if (st.isFile()) {\n searchPath = path.dirname(absTarget);\n const parentRelPath = path.posix.dirname(rel);\n searchRelPath = parentRelPath === '.' ? '.' : parentRelPath;\n messages.push({\n type: 'warning',\n description: `Search path \"${rel}\" is not a directory (it's a file). Searching the directory containing it instead: \"${searchRelPath}\"`,\n });\n } else {\n throw toolErr('NOT_A_DIRECTORY', 'Search path is not a directory.', {\n path: rel,\n hint: 'The search path must be a directory. Search looks for files/directories matching the query within directories. Use \".\" to search from the root, or provide a directory path.',\n });\n }\n }\n } catch (e: any) {\n // If it's already a ToolError, rethrow\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to stat search path.');\n }\n }\n\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const allResults: FsSearchEntry[] = [];\n const ignoredCount = { value: 0 };\n await searchDirectory(\n searchPath,\n searchRelPath,\n directory.path,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults + offset, // Search more to account for offset\n allResults,\n ignoredCount,\n ignoreCtx,\n this.config,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n\n // Sort by score (higher first), then by name\n allResults.sort((a, b) => {\n const scoreDiff = (b.score ?? 0) - (a.score ?? 0);\n if (scoreDiff !== 0) return scoreDiff;\n return a.name.localeCompare(b.name);\n });\n\n // Apply pagination\n const page = allResults.slice(offset, offset + maxResults);\n const next_offset = offset + page.length;\n const has_more = next_offset < allResults.length;\n\n const meta: PaginationMeta = {\n count: page.length,\n limit: maxResults,\n offset,\n has_more,\n next_offset: has_more ? next_offset : undefined,\n };\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: searchRelPath,\n });\n\n // Audit successful search operation\n auditFsOperation('search', context, true, undefined, {\n file_count: page.length,\n });\n\n const result: FsSearchOutput = {\n results: page,\n meta,\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n if (messages.length > 0) {\n result.messages = messages as ToolMessage[];\n }\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_search tool\n */\nexport async function executeFsSearch(\n config: Configuration,\n args: FsSearchArgs\n): Promise<ToolResult<FsSearchOutput>> {\n const executer = new FsSearchExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\r\nimport { fail } from '@devicelink-workspace/domain';\r\nimport type { ToolResult, ToolError } from '@devicelink-workspace/domain';\r\nimport { BaseExecuter } from './base-executer.js';\r\nimport { FsListExecuter } from './fs-list.js';\r\nimport { FsReadExecuter } from './fs-read.js';\r\nimport { FsInfoExecuter } from './fs-info.js';\r\nimport { FsTreeExecuter } from './fs-tree.js';\r\nimport { FsSearchExecuter } from './fs-search.js';\r\nimport { FsGrepExecuter } from './fs-grep.js';\r\nimport { FsReadManyExecuter } from './fs-read-many.js';\r\nimport type { ToolName, ToolArgs, ToolOutput } from './types.js';\r\n\r\n/**\r\n * Type guard to check if an error is a ToolError\r\n */\r\nfunction isToolError(e: unknown): e is ToolError {\r\n return (\r\n typeof e === 'object' &&\r\n e !== null &&\r\n 'code' in e &&\r\n 'message' in e &&\r\n typeof (e as any).code === 'string' &&\r\n typeof (e as any).message === 'string'\r\n );\r\n}\r\n\r\n/**\r\n * Tool executer registry class\r\n * Manages tool executers and provides a unified interface for executing tools\r\n */\r\nexport class ToolExecuterRegistry {\r\n private readonly config: Configuration;\r\n private readonly executers: Map<ToolName, BaseExecuter<any, any>> = new Map();\r\n\r\n constructor(config: Configuration) {\r\n this.config = config;\r\n this.initializeExecuters();\r\n }\r\n\r\n /**\r\n * Initialize all tool executers\r\n */\r\n private initializeExecuters(): void {\r\n this.executers.set('fs_list', new FsListExecuter(this.config));\r\n this.executers.set('fs_read', new FsReadExecuter(this.config));\r\n this.executers.set('fs_info', new FsInfoExecuter(this.config));\r\n this.executers.set('fs_tree', new FsTreeExecuter(this.config));\r\n this.executers.set('fs_search', new FsSearchExecuter(this.config));\r\n this.executers.set('fs_grep', new FsGrepExecuter(this.config));\r\n this.executers.set('fs_read_many', new FsReadManyExecuter(this.config));\r\n }\r\n\r\n /**\r\n * Execute a tool by name with properly typed arguments and return value\r\n *\r\n * @param toolName - Name of the tool to execute\r\n * @param args - Tool-specific arguments\r\n * @returns Tool result with typed output or error\r\n */\r\n public async executeTool(\r\n toolName: ToolName,\r\n args: ToolArgs\r\n ): Promise<ToolResult<ToolOutput>> {\r\n const executer = this.executers.get(toolName);\r\n\r\n if (!executer) {\r\n return fail({\r\n code: 'UNKNOWN_TOOL',\r\n message: `Unknown tool: ${toolName}`,\r\n details: { toolName },\r\n });\r\n }\r\n\r\n try {\r\n return await executer.execute(args);\r\n } catch (e: unknown) {\r\n if (isToolError(e)) {\r\n return fail(e);\r\n }\r\n return fail({\r\n code: 'INTERNAL',\r\n message: e instanceof Error ? e.message : 'Unknown error',\r\n details: { raw: String(e) },\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get a specific executer instance by tool name\r\n *\r\n * @param toolName - Name of the tool\r\n * @returns The executer instance or undefined if not found\r\n */\r\n public getExecuter<T extends ToolName>(toolName: T): BaseExecuter<any, any> | undefined {\r\n return this.executers.get(toolName);\r\n }\r\n\r\n /**\r\n * Check if a tool is registered\r\n *\r\n * @param toolName - Name of the tool\r\n * @returns True if the tool is registered\r\n */\r\n public hasTool(toolName: string): toolName is ToolName {\r\n return this.executers.has(toolName as ToolName);\r\n }\r\n\r\n /**\r\n * Get all registered tool names\r\n *\r\n * @returns Array of all registered tool names\r\n */\r\n public getRegisteredTools(): ToolName[] {\r\n return Array.from(this.executers.keys());\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function to execute a tool (creates a registry instance)\r\n * This maintains backward compatibility with the function-based API\r\n *\r\n * @param config - CLI Configuration\r\n * @param toolName - Name of the tool to execute\r\n * @param args - Tool-specific arguments\r\n * @returns Tool result with typed output or error\r\n */\r\nexport async function executeTool(\r\n config: Configuration,\r\n toolName: ToolName,\r\n args: ToolArgs\r\n): Promise<ToolResult<ToolOutput>> {\r\n const registry = new ToolExecuterRegistry(config);\r\n return await registry.executeTool(toolName, args);\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport isObject from 'lodash/isObject.js';\r\nimport get from 'lodash/get.js';\r\n\r\n/**\r\n * Calculate execution timing from start time\r\n */\r\nexport function calculateTiming(startTime: number): {\r\n execution_ms: number;\r\n execution_sec: number;\r\n} {\r\n const executionMs = Date.now() - startTime;\r\n const executionSec = parseFloat((executionMs / 1000).toFixed(2));\r\n return {\r\n execution_ms: executionMs,\r\n execution_sec: executionSec,\r\n };\r\n}\r\n\r\n/**\r\n * Check if a value is a ToolResult envelope (has 'ok' property)\r\n */\r\nexport function isToolResultEnvelope(value: unknown): value is ToolResult<unknown> {\r\n return isObject(value) && typeof get(value, 'ok') === 'boolean';\r\n}\r\n\r\n/**\r\n * Extract data from ToolResult envelope\r\n * Handles both envelope format (ok/data/error) and raw results\r\n */\r\nexport function extractToolResult<T = unknown>(\r\n raw: ToolResult<T> | T\r\n): {\r\n ok: boolean;\r\n result?: T;\r\n error?: unknown;\r\n messages?: unknown[];\r\n} {\r\n const hasEnvelope = isToolResultEnvelope(raw);\r\n const ok = hasEnvelope ? Boolean(get(raw, 'ok')) : true;\r\n \r\n let result: T | undefined;\r\n let error: unknown;\r\n let messages: unknown[] | undefined;\r\n\r\n if (ok) {\r\n // Success case\r\n if (hasEnvelope) {\r\n result = get(raw, 'data') ?? get(raw, 'result') ?? (raw as T);\r\n } else {\r\n result = raw as T;\r\n }\r\n\r\n // Extract messages if present\r\n if (isObject(result) && Array.isArray(get(result, 'messages'))) {\r\n messages = get(result, 'messages') as unknown[];\r\n result = { ...(result as any) };\r\n delete (result as any).messages;\r\n }\r\n } else {\r\n // Error case\r\n if (hasEnvelope) {\r\n error = get(raw, 'error') ?? raw;\r\n } else {\r\n error = raw;\r\n }\r\n }\r\n\r\n return { ok, result, error, messages };\r\n}\r\n\r\n/**\r\n * Create a ToolResultResponse-compatible object from ToolResult\r\n */\r\nexport function formatToolResultResponse(\r\n jobId: string,\r\n toolName: string,\r\n raw: ToolResult<unknown> | unknown,\r\n startTime: number\r\n): {\r\n type: 'tool_result';\r\n job_id: string;\r\n tool: string;\r\n ok: boolean;\r\n result?: unknown;\r\n error?: unknown;\r\n messages?: unknown[];\r\n timing: {\r\n execution_ms: number;\r\n execution_sec: number;\r\n };\r\n} {\r\n const timing = calculateTiming(startTime);\r\n const { ok, result, error, messages } = extractToolResult(raw);\r\n\r\n const toolResult: any = {\r\n type: 'tool_result',\r\n job_id: jobId,\r\n tool: toolName,\r\n ok,\r\n timing,\r\n };\r\n\r\n if (ok) {\r\n toolResult.result = result ?? null;\r\n } else {\r\n toolResult.error = error ?? { code: 'UNKNOWN', message: 'Unknown error' };\r\n }\r\n\r\n if (messages) {\r\n toolResult.messages = messages;\r\n }\r\n\r\n return toolResult;\r\n}\r\n\r\n/**\r\n * Create an error ToolResultResponse\r\n */\r\nexport function formatToolErrorResponse(\r\n jobId: string,\r\n toolName: string,\r\n error: unknown,\r\n startTime: number\r\n): {\r\n type: 'tool_result';\r\n job_id: string;\r\n tool: string;\r\n ok: false;\r\n error: string | { code: string; message: string };\r\n timing: {\r\n execution_ms: number;\r\n execution_sec: number;\r\n };\r\n} {\r\n const timing = calculateTiming(startTime);\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n\r\n return {\r\n type: 'tool_result',\r\n job_id: jobId,\r\n tool: toolName,\r\n ok: false,\r\n error: errorMessage,\r\n timing,\r\n };\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport type { ToolName } from '../executers/types.js';\r\n\r\n/**\r\n * Base class for tool results\r\n * Provides common functionality and toString() method\r\n */\r\nexport abstract class BaseToolResult {\r\n public readonly toolName: ToolName;\r\n public readonly jobId: string;\r\n public readonly ok: boolean;\r\n public readonly elapsedSec: number;\r\n public readonly raw: ToolResult<unknown>;\r\n\r\n constructor(\r\n toolName: ToolName,\r\n jobId: string,\r\n raw: ToolResult<unknown>,\r\n elapsedSec: number\r\n ) {\r\n this.toolName = toolName;\r\n this.jobId = jobId;\r\n this.ok = raw.ok;\r\n this.elapsedSec = elapsedSec;\r\n this.raw = raw;\r\n }\r\n\r\n /**\r\n * Abstract method that subclasses must implement\r\n * Returns a human-readable description of what the tool did\r\n */\r\n protected abstract getDescription(): string;\r\n\r\n /**\r\n * Get status indicator (\u2713 for success, \u2717 for error)\r\n */\r\n protected getStatusIcon(): string {\r\n return this.ok ? '\u2713' : '\u2717';\r\n }\r\n\r\n /**\r\n * Get status text\r\n */\r\n protected getStatusText(): string {\r\n return this.ok ? 'SUCCESS' : 'FAILED';\r\n }\r\n\r\n /**\r\n * Format the result as a string\r\n */\r\n public toString(): string {\r\n const status = this.getStatusIcon();\r\n const description = this.getDescription();\r\n return `${status} ${this.toolName} (${description}, elapsed=${this.elapsedSec}s)`;\r\n }\r\n}\r\n", "import type { FsListOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsListResult extends BaseToolResult {\r\n private readonly output?: FsListOutput;\r\n\r\n constructor(\r\n toolName: 'fs_list',\r\n jobId: string,\r\n raw: ToolResult<FsListOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { items, meta, filtered, context } = this.output;\r\n const itemCount = items?.length ?? 0;\r\n const totalCount = meta?.count ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n const path = context?.path ?? 'unknown';\r\n\r\n const parts: string[] = [];\r\n \r\n if (itemCount > 0) {\r\n parts.push(`${itemCount} item${itemCount !== 1 ? 's' : ''}`);\r\n }\r\n \r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.has_more) {\r\n parts.push('has_more');\r\n }\r\n\r\n const description = parts.length > 0 ? parts.join(', ') : 'empty';\r\n return `path=${path}, ${description}`;\r\n }\r\n}\r\n", "import type { FsReadOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsReadResult extends BaseToolResult {\r\n private readonly output?: FsReadOutput;\r\n\r\n constructor(\r\n toolName: 'fs_read',\r\n jobId: string,\r\n raw: ToolResult<FsReadOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { bytes_read, eof, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const size = bytes_read ?? 0;\r\n const truncated = !eof;\r\n\r\n const parts: string[] = [`path=${path}`, `${size} bytes`];\r\n \r\n if (truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsInfoOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsInfoResult extends BaseToolResult {\r\n private readonly output?: FsInfoOutput;\r\n\r\n constructor(\r\n toolName: 'fs_info',\r\n jobId: string,\r\n raw: ToolResult<FsInfoOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { type, size, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const sizeStr = size !== undefined ? `${size} bytes` : 'no size';\r\n\r\n return `path=${path}, type=${type}, ${sizeStr}`;\r\n }\r\n}\r\n", "import type { FsTreeOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsTreeResult extends BaseToolResult {\r\n private readonly output?: FsTreeOutput;\r\n\r\n constructor(\r\n toolName: 'fs_tree',\r\n jobId: string,\r\n raw: ToolResult<FsTreeOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { tree, filtered, summary, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [`path=${path}`];\r\n\r\n if (summary) {\r\n const { total_entries, files, dirs } = summary;\r\n if (total_entries !== undefined) {\r\n parts.push(`${total_entries} entries`);\r\n }\r\n if (files !== undefined) {\r\n parts.push(`${files} files`);\r\n }\r\n if (dirs !== undefined) {\r\n parts.push(`${dirs} dirs`);\r\n }\r\n } else if (tree) {\r\n // Count nodes recursively\r\n const countNodes = (node: typeof tree): number => {\r\n let count = 1;\r\n if (node.children) {\r\n for (const child of node.children) {\r\n count += countNodes(child);\r\n }\r\n }\r\n return count;\r\n };\r\n const nodeCount = countNodes(tree);\r\n parts.push(`${nodeCount} nodes`);\r\n }\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (this.output.truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsSearchOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsSearchResult extends BaseToolResult {\r\n private readonly output?: FsSearchOutput;\r\n\r\n constructor(\r\n toolName: 'fs_search',\r\n jobId: string,\r\n raw: ToolResult<FsSearchOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { results, meta, filtered, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const resultCount = results?.length ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [`path=${path}`, `${resultCount} result${resultCount !== 1 ? 's' : ''}`];\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.has_more) {\r\n parts.push('has_more');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsGrepOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsGrepResult extends BaseToolResult {\r\n private readonly output?: FsGrepOutput;\r\n\r\n constructor(\r\n toolName: 'fs_grep',\r\n jobId: string,\r\n raw: ToolResult<FsGrepOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { matches, meta, filtered, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const matchCount = matches?.length ?? 0;\r\n const filesScanned = meta?.files_scanned ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [\r\n `path=${path}`,\r\n `${matchCount} match${matchCount !== 1 ? 'es' : ''}`,\r\n `${filesScanned} file${filesScanned !== 1 ? 's' : ''} scanned`,\r\n ];\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsReadManyOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsReadManyResult extends BaseToolResult {\r\n private readonly output?: FsReadManyOutput;\r\n\r\n constructor(\r\n toolName: 'fs_read_many',\r\n jobId: string,\r\n raw: ToolResult<FsReadManyOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { files } = this.output;\r\n const fileCount = files?.length ?? 0;\r\n const successCount = files?.filter((f) => !f.error).length ?? 0;\r\n const errorCount = fileCount - successCount;\r\n const totalBytes = files?.reduce((sum, f) => sum + (f.bytes_read ?? 0), 0) ?? 0;\r\n\r\n const parts: string[] = [\r\n `${fileCount} file${fileCount !== 1 ? 's' : ''}`,\r\n `${successCount} success`,\r\n ];\r\n\r\n if (errorCount > 0) {\r\n parts.push(`${errorCount} error${errorCount !== 1 ? 's' : ''}`);\r\n }\r\n\r\n if (totalBytes > 0) {\r\n parts.push(`${totalBytes} bytes`);\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport type { ToolName } from '../executers/types.js';\r\nimport type {\r\n FsListOutput,\r\n FsReadOutput,\r\n FsInfoOutput,\r\n FsTreeOutput,\r\n FsSearchOutput,\r\n FsGrepOutput,\r\n FsReadManyOutput,\r\n} from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\nimport { FsListResult } from './fs-list-result.js';\r\nimport { FsReadResult } from './fs-read-result.js';\r\nimport { FsInfoResult } from './fs-info-result.js';\r\nimport { FsTreeResult } from './fs-tree-result.js';\r\nimport { FsSearchResult } from './fs-search-result.js';\r\nimport { FsGrepResult } from './fs-grep-result.js';\r\nimport { FsReadManyResult } from './fs-read-many-result.js';\r\n\r\n/**\r\n * Create a tool result instance based on tool name\r\n */\r\nexport function createToolResult(\r\n toolName: ToolName,\r\n jobId: string,\r\n raw: ToolResult<unknown>,\r\n elapsedSec: number\r\n): BaseToolResult {\r\n switch (toolName) {\r\n case 'fs_list':\r\n return new FsListResult(toolName, jobId, raw as ToolResult<FsListOutput>, elapsedSec);\r\n case 'fs_read':\r\n return new FsReadResult(toolName, jobId, raw as ToolResult<FsReadOutput>, elapsedSec);\r\n case 'fs_info':\r\n return new FsInfoResult(toolName, jobId, raw as ToolResult<FsInfoOutput>, elapsedSec);\r\n case 'fs_tree':\r\n return new FsTreeResult(toolName, jobId, raw as ToolResult<FsTreeOutput>, elapsedSec);\r\n case 'fs_search':\r\n return new FsSearchResult(toolName, jobId, raw as ToolResult<FsSearchOutput>, elapsedSec);\r\n case 'fs_grep':\r\n return new FsGrepResult(toolName, jobId, raw as ToolResult<FsGrepOutput>, elapsedSec);\r\n case 'fs_read_many':\r\n return new FsReadManyResult(toolName, jobId, raw as ToolResult<FsReadManyOutput>, elapsedSec);\r\n default: {\r\n // Fallback to base result for unknown tools\r\n class DefaultToolResult extends BaseToolResult {\r\n protected getDescription(): string {\r\n return this.ok ? 'completed' : 'failed';\r\n }\r\n }\r\n return new DefaultToolResult(toolName, jobId, raw, elapsedSec);\r\n }\r\n }\r\n}\r\n\r\nexport { BaseToolResult } from './base-result.js';\r\nexport { FsListResult } from './fs-list-result.js';\r\nexport { FsReadResult } from './fs-read-result.js';\r\nexport { FsInfoResult } from './fs-info-result.js';\r\nexport { FsTreeResult } from './fs-tree-result.js';\r\nexport { FsSearchResult } from './fs-search-result.js';\r\nexport { FsGrepResult } from './fs-grep-result.js';\r\nexport { FsReadManyResult } from './fs-read-many-result.js';\r\n", "import { WsConnected, WsRx } from \"../../core/events.js\";\nimport { Orchestrator, OrchestratorContext } from \"../../core/orchestrator.js\";\nimport { NotifyScope, NotifyKind } from \"../../core/types.js\";\nimport { BridgeOutboundMsgSchema, ToolResultResponseSchema } from \"@devicelink-workspace/domain\";\nimport type { ToolCallRequest, ToolResult } from \"@devicelink-workspace/domain\";\nimport { ToolExecuterRegistry } from \"./executers\";\nimport type { ToolName, ToolArgs } from \"./executers/types.js\";\nimport { formatToolResultResponse, formatToolErrorResponse, calculateTiming } from \"./utils.js\";\nimport { createToolResult } from \"./results/index.js\";\n\nexport class ToolsOrchestrator implements Orchestrator {\n public readonly name = \"tools-orchestrator\";\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public handlers() {\n return {\n \"ws:connected\": async (payload: WsConnected, ctx: OrchestratorContext) => {\n ctx.notifier.info(`WS connected: ${payload.url}`, { scope: NotifyScope.System });\n },\n\n \"ws:rx\": async (payload: WsRx, ctx: OrchestratorContext) => {\n // Parse message to identify tool_call messages\n try {\n const obj = JSON.parse(payload.text);\n const parsed = BridgeOutboundMsgSchema.safeParse(obj);\n if (!parsed.success) {\n ctx.notifier.error('Unexpected message format');\n return;\n }\n\n const msg = parsed.data;\n\n if (parsed.success && parsed.data.type === 'tool_call') {\n // Handle tool_call\n await this.handleToolCall(parsed.data, ctx);\n }\n } catch (e: any) {\n // Not a tool_call or parse failed, ignore\n ctx.notifier.error('Unexpected message format');\n }\n },\n };\n }\n\n private async handleToolCall(call: ToolCallRequest, ctx: OrchestratorContext): Promise<void> {\n const toolName = call.tool as ToolName;\n const jobId = call.job_id;\n const args = call.args ?? {};\n\n // Debug: log args to see if directory_id is present\n const directoryId = args['directory_id'] as string;\n const config = ctx.engine.configurationContext.configuration;\n const availableDirectoryIds = config.directories.map(r => r.id).join(', ') || 'none';\n const availableDirectoryPaths = config.directories.map(r => r.path).join(', ') || 'none';\n ctx.notifier.info(`Tool call: ${toolName} (job=${jobId}, directory_id=${directoryId || 'MISSING'}, available_ids=[${availableDirectoryIds}], available_paths=[${availableDirectoryPaths}], directory_count=${config.directories.length})`, { scope: NotifyScope.System });\n\n const toolStartTime = Date.now();\n\n try {\n const toolRegistry = new ToolExecuterRegistry(config);\n const raw = await toolRegistry.executeTool(toolName, args as ToolArgs);\n\n const toolResult = formatToolResultResponse(jobId, toolName, raw, toolStartTime);\n\n // Validate with schema\n ToolResultResponseSchema.parse(toolResult);\n\n // Send result back via WebSocket\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolResult) });\n\n // Create result object with toString() for better logging\n const timing = calculateTiming(toolStartTime);\n const result = createToolResult(toolName, jobId, raw, timing.execution_sec);\n\n // Use appropriate notifier based on success/failure\n if (result.ok) {\n ctx.notifier.success(result.toString(), { ts: Date.now(), kind: NotifyKind.Success, scope: NotifyScope.System });\n } else {\n ctx.notifier.error(result.toString(), { scope: NotifyScope.System });\n }\n } catch (e: unknown) {\n const toolResult = formatToolErrorResponse(jobId, toolName, e, toolStartTime);\n\n // Validate with schema\n ToolResultResponseSchema.parse(toolResult);\n\n // Send error result back via WebSocket\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolResult) });\n\n // Create error result object for consistent logging\n const timing = calculateTiming(toolStartTime);\n const errorResult: ToolResult<unknown> = {\n ok: false,\n error: e instanceof Error ? { code: 'INTERNAL', message: e.message } : { code: 'INTERNAL', message: String(e) },\n };\n const result = createToolResult(toolName, jobId, errorResult, timing.execution_sec);\n ctx.notifier.error(result.toString(), { scope: NotifyScope.System });\n }\n }\n}\n", "/**\n * Supported tools list - filesystem tools only\n * These are the tools that the agent can execute locally\n */\n\nexport const supportedTools = [\n {\n name: 'fs_list',\n version: '1.0',\n description: 'List files and folders at a relative path inside a shared folder.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n limit: { type: 'integer', minimum: 1, maximum: 1000, default: 200 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n sort: { type: 'string', enum: ['name', 'mtime', 'size'], default: 'name' },\n order: { type: 'string', enum: ['asc', 'desc'], default: 'asc' },\n detail: { type: 'string', enum: ['basic', 'stat', 'digest'], default: 'stat' },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_read',\n version: '1.0',\n description:\n 'Read the contents of a SINGLE text file inside a shared folder. For reading many files at once, prefer fs_read_many instead of multiple fs_read calls.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', minLength: 1 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n limit: { type: 'integer', minimum: 1, maximum: 200000, default: 40000 },\n encoding: { type: 'string', default: 'utf-8' },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_FILE', 'PERMISSION_DENIED', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_info',\n version: '1.0',\n description: 'Get metadata about a file or directory (type, size, timestamps, symlink).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', minLength: 1 },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'PERMISSION_DENIED', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_tree',\n version: '1.0',\n description: 'Return a directory tree from a relative path up to max_depth.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n max_depth: { type: 'integer', minimum: 1, maximum: 20, default: 3 },\n max_entries: { type: 'integer', minimum: 1, maximum: 20000, default: 5000 },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n detail: { type: 'string', enum: ['basic', 'stat', 'digest'], default: 'stat' },\n include_display: { type: 'boolean', default: false },\n max_display_rows: { type: 'integer', minimum: 1, maximum: 20000, default: 2000 },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_search',\n version: '1.0',\n description: 'Search for files/folders by name inside a root, optionally recursively.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n query: { type: 'string', minLength: 1 },\n mode: { type: 'string', enum: ['substring', 'glob'], default: 'substring' },\n recursive: { type: 'boolean', default: true },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n max_results: { type: 'integer', minimum: 1, maximum: 20000, default: 200 },\n },\n required: ['query'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_grep',\n version: '1.0',\n description: 'Search for text content inside files (like grep/ripgrep).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n query: { type: 'string', minLength: 1 },\n mode: { type: 'string', enum: ['substring', 'regex'], default: 'substring' },\n file_glob: { type: 'string' },\n max_files: { type: 'integer', minimum: 1, maximum: 10000, default: 2000 },\n max_matches: { type: 'integer', minimum: 1, maximum: 1000, default: 200 },\n context_lines: { type: 'integer', minimum: 0, maximum: 10, default: 2 },\n case_sensitive: { type: 'boolean', default: false },\n },\n required: ['query'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL'],\n },\n {\n name: 'fs_read_many',\n version: '1.0',\n description:\n 'Read multiple files in a single call (batch read). Prefer this over multiple fs_read calls when you need to read several files\u2014fewer round-trips and better performance (up to 50 items per call).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n items: {\n type: 'array',\n minItems: 1,\n maxItems: 50,\n items: {\n type: 'object',\n properties: {\n path: { type: 'string', minLength: 1 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n limit: { type: 'integer', minimum: 1, maximum: 200000 },\n encoding: { type: 'string' },\n },\n required: ['path'],\n },\n },\n default_limit: { type: 'integer', minimum: 1, maximum: 200000, default: 12000 },\n default_encoding: { type: 'string', default: 'utf-8' },\n },\n required: ['items'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_FILE', 'INVALID_INPUT', 'INTERNAL'],\n },\n] as const;\n", "import { supportedTools } from \"../../../tools/supported-items\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../../../core/job\";\nimport { NotifyScope } from \"../../../core/types\";\nimport type { ToolDef, ToolsPublishRequest } from \"@devicelink-workspace/domain\";\n\n\nexport class SupportedToolsJob extends JobType<void, void> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"tools-job\",\n lane: \"worker\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(_input: void, ctx: JobContext): Promise<void> {\n ctx.notifier.info(`Executing supported tools job`);\n \n const config = ctx.engine.configurationContext.configuration;\n const deviceId = config.device?.id;\n \n if (!deviceId) {\n ctx.notifier.error(`Cannot publish tools: device ID not available`);\n return;\n }\n \n const toolsPublish: ToolsPublishRequest = {\n type: 'tools_publish',\n device_id: deviceId,\n tools: supportedTools as unknown as ToolDef[],\n };\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolsPublish) });\n ctx.notifier.success(`\u2192 tools_publish (count=${supportedTools.length})`);\n return;\n }\n}\n\nexport const supportedToolsJob = new SupportedToolsJob();\n\n\nexport function supportedToolsCall(): JobCall<void, void> {\n return new JobCall(supportedToolsJob, void 0);\n}\n", "\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../../../core/job\";\nimport { NotifyScope } from \"../../../core/types\";\nimport type { DirectoriesPublishRequest } from \"@devicelink-workspace/domain\";\n\n\nexport class DirectoriesJob extends JobType<void, void> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"directories-job\",\n lane: \"worker\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(_input: void, ctx: JobContext): Promise<void> {\n ctx.notifier.info(`Executing directories job`);\n \n const config = ctx.engine.configurationContext.configuration;\n const deviceId = config.device?.id;\n \n if (!deviceId) {\n ctx.notifier.error(`Cannot publish directories: device ID not available`);\n return;\n }\n \n const directories = config.directories.map((r) => {\n return {\n id: r.id,\n name: r.name,\n path: r.path,\n path_hint: r.tag || undefined,\n };\n });\n \n const directoriesPublish: DirectoriesPublishRequest = {\n type: 'directories_publish',\n device_id: deviceId,\n directories,\n };\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(directoriesPublish) });\n ctx.notifier.success(`\u2192 directories_publish (dirs=${directoriesPublish.directories.length})`);\n return;\n }\n}\n\nexport const directoriesJob = new DirectoriesJob();\n\n\nexport function directoriesCall(): JobCall<void, void> {\n return new JobCall(directoriesJob, void 0);\n}\n", "import { WsConnected } from \"../../core/events.js\";\nimport { Orchestrator, OrchestratorContext } from \"../../core/orchestrator.js\";\nimport { NotifyScope } from \"../../core/types.js\";\nimport { supportedToolsCall, supportedToolsJob } from \"./jobs/supported-tools.job.js\";\nimport { directoriesCall, directoriesJob } from \"./jobs/directories.job.js\";\n\nexport class MetaDataOrchestrator implements Orchestrator {\n public readonly name = \"meta-data-orchestrator\";\n\n public onRegister(_ctx: OrchestratorContext): void {\n _ctx.engine.register(supportedToolsJob);\n _ctx.engine.register(directoriesJob);\n }\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public handlers() {\n return {\n \"meta:data:requested:tools\": async (payload: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(`MetaData: tools requested -> dispatching supported tools job`);\n ctx.engine.dispatch(supportedToolsCall());\n },\n \"meta:data:requested:directories\": async (payload: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(`MetaData: directories requested -> dispatching directories job`);\n ctx.engine.dispatch(directoriesCall());\n },\n };\n }\n}\n", "\r\n\r\nexport class ArgvContext {\r\n\r\n public readonly enviromentFile?: string;\r\n public readonly rootPath?: string;\r\n public readonly controlUrl?: string;\r\n public readonly bridgeWsUrl?: string;\r\n public readonly privateKeyFile?: string;\r\n public readonly publicKeyFile?: string;\r\n\r\n constructor(public readonly argv: string[]) {\r\n const trimmedArgv = argv.map(arg => arg.trim()?.toLowerCase());\r\n const originalArgv = argv.map(arg => arg.trim());\r\n const envResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--env']);\r\n if (envResult.match) {\r\n this.enviromentFile = envResult.value;\r\n }\r\n const rootResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--root']);\r\n if (rootResult.match) {\r\n this.rootPath = rootResult.value;\r\n }\r\n const controlUrlResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--control-url']);\r\n if (controlUrlResult.match) {\r\n this.controlUrl = controlUrlResult.value;\r\n }\r\n const bridgeWsUrlResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--bridge-ws-url']);\r\n if (bridgeWsUrlResult.match) {\r\n this.bridgeWsUrl = bridgeWsUrlResult.value;\r\n }\r\n const privateKeyFileResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--private-key-file']);\r\n if (privateKeyFileResult.match && privateKeyFileResult.value) {\r\n this.privateKeyFile = privateKeyFileResult.value;\r\n }\r\n const publicKeyFileResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--public-key-file']);\r\n if (publicKeyFileResult.match && publicKeyFileResult.value) {\r\n this.publicKeyFile = publicKeyFileResult.value;\r\n }\r\n }\r\n\r\n private parseKeyValue(lowerArgv: string[], originalArgv: string[], keys: string[]): {\r\n match: boolean;\r\n value?: string;\r\n } {\r\n const lowerCaseKeys = keys.map(key => key.toLowerCase()?.trim()).filter(key => key !== undefined);\r\n if (lowerCaseKeys.length === 0) {\r\n return { match: false, value: undefined };\r\n }\r\n for (const key of lowerCaseKeys) {\r\n const index = lowerArgv.findIndex(arg => {\r\n const lowerArg = arg.toLowerCase();\r\n // Handle both --key=value and --key formats\r\n return lowerArg === key || lowerArg.startsWith(key + '=');\r\n });\r\n if (index !== -1) {\r\n const originalArg = originalArgv[index]!;\r\n // Check if value is in the same argument (--key=value format)\r\n const equalsIndex = originalArg.toLowerCase().indexOf('=');\r\n if (equalsIndex !== -1) {\r\n const value = originalArg.substring(equalsIndex + 1);\r\n return { match: true, value: value || undefined };\r\n }\r\n // Otherwise, value is in the next argument (--key value format)\r\n return { match: true, value: originalArgv[index + 1] ?? undefined };\r\n }\r\n }\r\n return { match: false, value: undefined };\r\n }\r\n}\r\n", "import { EngineBus } from './eventBus';\nimport { NotifyEvent, NotifyOptions } from './events';\nimport { NotifyKind, NotifyScope, RuntimeFlags } from './types';\n\nexport class Notifier {\n private readonly bus: EngineBus;\n private readonly flags: RuntimeFlags;\n\n public constructor(bus: EngineBus, flags?: RuntimeFlags) {\n this.bus = bus;\n this.flags = flags ?? new RuntimeFlags(false);\n }\n\n public info(\n message: string,\n options?: NotifyOptions,\n ): NotifyEvent | null {\n return this.push(\n message,\n options,\n );\n }\n\n public warn(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Warning });\n return this.push(message, opts);\n }\n\n public error(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Error });\n return this.push(message, opts);\n }\n\n public success(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Success });\n return this.push(message, opts);\n }\n\n private push(\n message: string,\n options?: NotifyOptions,\n ): NotifyEvent | null {\n if (options?.scope === NotifyScope.System && !this.flags.debug) {\n return null;\n }\n\n const entry = new NotifyEvent(message, options);\n this.bus.emit('notify:event', entry);\n return entry;\n }\n}\n", "import { EngineBus } from \"./eventBus\";\nimport { LogEntry, LogOptions } from \"./events\";\nimport { LogLevel } from \"./types\";\n\n\nexport class Logger {\n private readonly bus: EngineBus;\n\n public constructor(bus: EngineBus) {\n this.bus = bus;\n }\n\n public info(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Info }));\n }\n\n public warn(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Warn }));\n }\n\n public error(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Error }));\n }\n\n public debug(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Debug }));\n }\n\n public success(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Success }));\n }\n\n private push(message: string, options?: LogOptions): void {\n const entry = new LogEntry(message, options);\n this.bus.emit(\"log\", entry);\n }\n}\n", "#!/usr/bin/env node\nimport { Engine } from \"./core/engine\";\nimport { EventBus } from \"./core/eventBus\";\nimport { MemoryStorage } from \"./core/storage\";\nimport { LaneConfig, RuntimeFlags } from \"./core/types\";\nimport { EngineEventMap } from \"./core/events\";\nimport { createStorage } from \"../storage/index.js\";\n\nimport { loadConfigJob } from \"./jobs/loadConfig\";\nimport { consoleCommandJob } from \"./jobs/consoleCommand\";\nimport { contactServerJob } from \"./jobs/contactServer\";\nimport { sendServerResultJob } from \"./jobs/sendServerResult\";\nimport { refreshTokensJob } from \"./jobs/refreshTokens\";\n\nimport { TelemetryOrchestrator } from \"./orchestrators/telemetry.orchestrator\";\nimport { OSSignalOrchestrator } from \"./orchestrators/os-signal.orchestrator\";\nimport { ConsoleOrchestrator } from \"./orchestrators/console.orchestrator\";\nimport { WebSocketOrchestrator } from \"./orchestrators/socket.orchestrator\";\nimport { MainOrchestrator } from \"./orchestrators/main.orchestrator\";\nimport { AuthOrchestrator } from \"./orchestrators/auth.orchestrator\";\nimport { ToolsOrchestrator } from \"./orchestrators/tools/index.js\";\nimport { MetaDataOrchestrator } from \"./orchestrators/meta-data/index.js\";\nimport { ArgvContext } from \"./core/context\";\nimport { Notifier } from \"./core/notifier\";\nimport { Logger } from \"./core/logger\";\n\nasync function main(): Promise<void> {\n const bus = new EventBus<EngineEventMap>();\n\n const storage = new MemoryStorage();\n const secretStorage = await createStorage();\n const argv = new ArgvContext(process.argv);\n\n const flags = new RuntimeFlags(false);\n const logger = new Logger(bus);\n const notifier = new Notifier(bus, flags);\n\n const engine = new Engine({\n bus,\n argv,\n logger,\n notifier,\n storage,\n secrets: secretStorage,\n flags,\n lanes: [\n new LaneConfig(\"console\", 1),\n new LaneConfig(\"supervisor\", 1),\n new LaneConfig(\"main\", 1),\n new LaneConfig(\"ws\", 1),\n new LaneConfig(\"worker\", 8),\n new LaneConfig(\"io\", 4),\n ],\n });\n\n engine.register(loadConfigJob);\n engine.register(refreshTokensJob);\n engine.register(consoleCommandJob);\n engine.register(contactServerJob);\n engine.register(sendServerResultJob);\n\n engine.registerOrchestrator(new ConsoleOrchestrator());\n engine.registerOrchestrator(new TelemetryOrchestrator(\"./engine_state/telemetry.ndjson\"));\n engine.registerOrchestrator(new OSSignalOrchestrator());\n engine.registerOrchestrator(new MainOrchestrator());\n engine.registerOrchestrator(new AuthOrchestrator());\n engine.registerOrchestrator(new WebSocketOrchestrator());\n engine.registerOrchestrator(new ToolsOrchestrator());\n engine.registerOrchestrator(new MetaDataOrchestrator());\n\n await engine.init();\n\n await engine.start();\n}\n\nvoid main();\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["crypto", "path", "os", "fs", "get", "isEmpty", "require", "crypto", "crypto", "crypto", "path", "path", "fs", "os", "isEmpty", "get", "directory", "Engine", "crypto", "crypto", "fs", "path", "os", "defaultTo", "ok", "ok", "
|
|
3
|
+
"sources": ["../../agent/src/cli/core/engine.ts", "../../agent/src/cli/core/types.ts", "../../agent/src/cli/core/result.ts", "../../agent/src/cli/core/job.ts", "../../agent/src/cli/core/events.ts", "../../agent/src/cli/core/storage.ts", "../../agent/src/cli/core/orchestrator.ts", "../../agent/src/cli/core/configuration.ts", "../../agent/src/cli/utils/config.builder.ts", "../../agent/src/cli/utils/machine-id.ts", "../../agent/src/cli/utils/key.builder.ts", "../../agent/src/cli/utils/get-directory-tag.ts", "../../common/src/lib/utils/crypto.utils.ts", "../../common/src/lib/utils/async.utils.ts", "../../common/src/lib/utils/path-display.utils.ts", "../../common/src/lib/utils/path.utils.ts", "../../agent/src/cli/core/eventBus.ts", "../../agent/src/storage/index.ts", "../../agent/src/cli/jobs/loadConfig.ts", "../../agent/src/cli/jobs/consoleCommand.ts", "../../agent/src/cli/jobs/contactServer.ts", "../../agent/src/cli/jobs/sendServerResult.ts", "../../agent/src/cli/jobs/refreshTokens.ts", "../../agent/src/cli/api/api.call.ts", "../../agent/src/cli/api/definitions/device-auth-start.api.ts", "../../agent/src/cli/api/definitions/device-auth-prove.api.ts", "../../agent/src/cli/api/definitions/device-auth-stream.api.ts", "../../agent/src/cli/api/definitions/device-auth-token.api.ts", "../../agent/src/cli/api/definitions/device-auth-refresh.api.ts", "../../agent/src/cli/api/index.ts", "../../agent/src/cli/orchestrators/telemetry.orchestrator.ts", "../../agent/src/cli/orchestrators/os-signal.orchestrator.ts", "../../agent/src/cli/ui/index.tsx", "../../agent/src/cli/ui/app.tsx", "../../agent/src/cli/ui/hooks/useStdoutDimensions.ts", "../../agent/src/cli/ui/components/StatusBar.tsx", "../../agent/src/cli/ui/context/AppContext.tsx", "../../agent/src/cli/ui/components/LogPane.tsx", "../../agent/src/cli/ui/components/InputBar.tsx", "../../agent/src/cli/ui/components/ErrorBoundary.tsx", "../../agent/src/cli/utils/command.parser.ts", "../../agent/src/cli/utils/command-job.builder.ts", "../../agent/src/cli/orchestrators/console.orchestrator.ts", "../../agent/src/cli/utils/recoverable-socket.ts", "../../agent/src/cli/orchestrators/socket.orchestrator.ts", "../../agent/src/cli/utils/configuration.writer.ts", "../../agent/src/cli/orchestrators/main.orchestrator.ts", "../../agent/src/cli/orchestrators/auth.orchestrator.ts", "../../domain/src/lib/schemas/socket.schemas.ts", "../../domain/src/lib/schemas/device-auth.schemas.ts", "../../domain/src/lib/models/tools/base.ts", "../../agent/src/cli/utils/scheduler.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-list.ts", "../../agent/src/cli/orchestrators/tools/executers/base-executer.ts", "../../agent/src/cli/orchestrators/tools/util/ignore.ts", "../../agent/src/cli/orchestrators/tools/util/_util.ts", "../../agent/src/cli/orchestrators/tools/util/_audit.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-read.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-info.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-tree.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-grep.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-read-many.ts", "../../agent/src/cli/orchestrators/tools/executers/fs-search.ts", "../../agent/src/cli/orchestrators/tools/executers/index.ts", "../../agent/src/cli/orchestrators/tools/utils.ts", "../../agent/src/cli/orchestrators/tools/results/base-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-list-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-read-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-info-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-tree-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-search-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-grep-result.ts", "../../agent/src/cli/orchestrators/tools/results/fs-read-many-result.ts", "../../agent/src/cli/orchestrators/tools/results/index.ts", "../../agent/src/cli/orchestrators/tools/index.ts", "../../agent/src/cli/tools/supported-items.ts", "../../agent/src/cli/orchestrators/meta-data/jobs/supported-tools.job.ts", "../../agent/src/cli/orchestrators/meta-data/jobs/directories.job.ts", "../../agent/src/cli/orchestrators/meta-data/index.ts", "../../agent/src/cli/core/context.ts", "../../agent/src/cli/core/notifier.ts", "../../agent/src/cli/core/logger.ts", "../../agent/src/cli/index.ts"],
|
|
4
|
+
"sourcesContent": ["import crypto from \"node:crypto\";\nimport { DispatchResult, Deferred } from \"./result\";\nimport { EngineBus, Subscription } from \"./eventBus\";\nimport { Logger } from \"./logger\";\nimport { JobContext, JobCall, JobType } from \"./job\";\nimport { EnginePhase, JobState, LaneConfig, NotifyScope, RuntimeFlags } from \"./types\";\nimport { EngineEventMap, JobEvent } from \"./events\";\nimport { EngineStateFile, PersistedJob, Storage } from \"./storage\";\nimport { Orchestrator, OrchestratorContext } from \"./orchestrator\";\nimport { ArgvContext } from \"./context\";\nimport { Notifier } from \"./notifier\";\nimport { Configuration, ConfigurationContext } from \"./configuration\";\nimport { ConfigLoader } from \"../utils/config.builder\";\nimport { BaseStorage } from \"agent/src/storage\";\n\nexport class DispatchOptions {\n public readonly dedupeKey: string | null;\n public readonly parentId: string | null;\n public readonly overridePriority: number | null;\n public readonly overrideLane: string | null;\n\n public constructor(\n dedupeKey: string | null,\n parentId: string | null,\n overridePriority: number | null,\n overrideLane: string | null\n ) {\n this.dedupeKey = dedupeKey;\n this.parentId = parentId;\n this.overridePriority = overridePriority;\n this.overrideLane = overrideLane;\n }\n}\n\n\nexport class EngineRuntime {\n public phase: EnginePhase;\n public readonly flags: RuntimeFlags;\n\n public constructor(flags?: RuntimeFlags) {\n this.phase = EnginePhase.Idle;\n this.flags = flags ?? new RuntimeFlags(false);\n }\n}\n\nexport class Engine {\n public readonly argv: ArgvContext;\n public readonly configurationContext: ConfigurationContext;\n \n private readonly bus: EngineBus;\n private readonly notifier: Notifier;\n private readonly logger: Logger;\n private readonly storage: Storage;\n public readonly secrets: BaseStorage;\n\n public readonly runtime: EngineRuntime;\n\n private readonly lanes: Map<string, LaneConfig>;\n private readonly laneActive: Map<string, number>;\n\n private readonly registry: Map<string, JobType<unknown, unknown>>;\n\n private readonly orchestrators: Orchestrator[];\n private readonly orchestratorSubscriptions: Map<string, Subscription[]> = new Map();\n private readonly orchestratorAbort: AbortController;\n\n private readonly jobs: Map<string, PersistedJob>;\n private readonly queue: Array<string>;\n\n private readonly locksHeldBy: Map<string, string>;\n\n private readonly completions: Map<string, Deferred<DispatchResult<unknown>>>;\n private readonly dedupeIndex: Map<string, string>;\n\n private readonly engineAbort: AbortController;\n private readonly jobAbort: Map<string, AbortController>;\n\n private stopping: boolean;\n private running: boolean;\n\n private wakeFn: (() => void) | null;\n private wakePromise: Promise<void>;\n\n public constructor(params: {\n argv: ArgvContext;\n bus: EngineBus;\n secrets: BaseStorage;\n notifier: Notifier;\n logger: Logger;\n storage: Storage;\n lanes: readonly LaneConfig[];\n flags?: RuntimeFlags;\n }) {\n this.argv = params.argv;\n this.bus = params.bus;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.storage = params.storage;\n this.secrets = params.secrets;\n\n this.runtime = new EngineRuntime(params.flags);\n\n this.lanes = new Map();\n for (const lane of params.lanes) {\n this.lanes.set(lane.name, lane);\n }\n\n this.laneActive = new Map();\n for (const lane of params.lanes) {\n this.laneActive.set(lane.name, 0);\n }\n\n this.registry = new Map();\n\n this.orchestrators = [];\n this.orchestratorAbort = new AbortController();\n\n this.jobs = new Map();\n this.queue = [];\n\n this.locksHeldBy = new Map();\n\n this.completions = new Map();\n this.dedupeIndex = new Map();\n\n this.engineAbort = new AbortController();\n this.jobAbort = new Map();\n\n this.stopping = false;\n this.running = false;\n\n this.wakeFn = null;\n this.wakePromise = this.resetWake();\n\n const config = new Configuration();\n const configLoader = new ConfigLoader(this.notifier);\n this.configurationContext = new ConfigurationContext(config, configLoader);\n }\n\n public applyConfiguration(configuration: Configuration): void {\n this.configurationContext.apply(configuration);\n }\n\n public setPhase(phase: EnginePhase): void {\n this.runtime.phase = phase;\n }\n\n public getBus(): EngineBus {\n return this.bus;\n }\n\n public hasRunningJobs(): boolean {\n for (const [, count] of this.laneActive) {\n if (count > 0) return true;\n }\n return false;\n }\n\n public register(jobType: JobType<unknown, unknown>): void {\n const name = jobType.options.name;\n if (this.registry.has(name)) {\n throw new Error(`JobType already registered: ${name}`);\n }\n this.registry.set(name, jobType);\n }\n\n public registerOrchestrator(orch: Orchestrator): void {\n const exists = this.orchestrators.some((o) => o.name === orch.name);\n if (exists) {\n throw new Error(`Orchestrator already registered: ${orch.name}`);\n }\n\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n orch.onRegister?.(ctx);\n this.setupOrchestratorSubscriptions(orch, ctx);\n this.orchestrators.push(orch);\n }\n\n private setupOrchestratorSubscriptions(orch: Orchestrator, ctx: OrchestratorContext): void {\n const map = orch.handlers?.();\n if (map) {\n const subs: Subscription[] = [];\n (Object.keys(map) as Array<keyof EngineEventMap>).forEach((eventName) => {\n const fn = map[eventName];\n if (!fn) return;\n \n subs.push(\n this.bus.on(eventName, (payload: EngineEventMap[keyof EngineEventMap]) => {\n // don't let exceptions crash emit()\n Promise.resolve(fn(payload as never, ctx)).catch((err) => {\n this.notifier.error(\n `handler error (${orch.name}/${String(eventName)}): ${String(err)}`,\n { scope: NotifyScope.System }\n );\n });\n })\n );\n });\n this.orchestratorSubscriptions.set(orch.name, subs);\n }\n }\n\n public async init(): Promise<void> {\n const state = await this.storage.load();\n for (const [id, job] of Object.entries(state.jobs)) {\n this.jobs.set(id, new PersistedJob(job));\n }\n\n // Crash recovery: running -> queued\n for (const job of this.jobs.values()) {\n if (job.state === JobState.Running) {\n job.state = JobState.Queued;\n job.nextRunAt = Date.now();\n job.updatedAt = Date.now();\n }\n if (job.dedupeKey) this.dedupeIndex.set(job.dedupeKey, job.id);\n if (job.state === JobState.Queued) this.queue.push(job.id);\n }\n }\n\n\n public async start(): Promise<void> {\n if (this.running) return;\n\n this.running = true;\n this.runtime.phase = EnginePhase.Running;\n\n // Make process-level crashes go through stop, not kill loop silently\n process.on(\"uncaughtException\", (err) => {\n this.notifier.error(`uncaughtException: ${err.stack ? err.stack : String(err)}`, { scope: NotifyScope.System });\n this.requestStop(\"uncaughtException\");\n });\n process.on(\"unhandledRejection\", (reason) => {\n this.notifier.error(`unhandledRejection: ${String(reason)}`, { scope: NotifyScope.System });\n // policy: keep running; user can stop\n });\n\n this.bus.emit(\"engine:started\", Date.now());\n\n\n try {\n // Start orchestrators, but don't let long-running tasks block scheduler.\n await this.startOrchestratorsSafe();\n \n // Run scheduler until stopping\n await this.loopGuarded();\n } finally {\n // Ensure orchestrators are stopped exactly once\n await this.stopOrchestratorsSafe();\n await this.persist();\n this.bus.emit(\"engine:stopped\", Date.now());\n }\n }\n\n public requestStop(reason: string): void {\n if (this.stopping) return;\n this.stopping = true;\n this.runtime.phase = EnginePhase.Stopping;\n this.bus.emit(\"engine:stopping\", reason);\n \n this.engineAbort.abort(new Error(`Stopping: ${reason}`));\n this.orchestratorAbort.abort(new Error(`Stopping: ${reason}`));\n \n // cancel running jobs (your logic is fine)\n for (const [jobId, ctrl] of this.jobAbort.entries()) {\n const job = this.jobs.get(jobId);\n if (job?.cancellable) ctrl.abort(new Error(\"Cancelled by user\"));\n }\n \n this.wake();\n }\n\n\n public async dispatch<TIn, TOut>(\n job: JobCall<TIn, TOut>,\n options?: DispatchOptions\n ): Promise<DispatchResult<TOut>> {\n const opts = options ? options : new DispatchOptions(null, null, null, null);\n\n const jobTypeName = job.type.options.name;\n\n // Ensure job type is registered\n if (!this.registry.has(jobTypeName)) {\n const err = new Error(`JobType not registered: ${jobTypeName}`);\n return DispatchResult.failure<TOut>(err);\n }\n\n // dedupe behavior if key provided\n if (opts.dedupeKey) {\n const existingId = this.dedupeIndex.get(opts.dedupeKey);\n if (existingId) {\n const existing = this.jobs.get(existingId);\n if (existing && (existing.state === JobState.Queued || existing.state === JobState.Running)) {\n const existingCompletion = this.completions.get(existingId);\n if (existingCompletion) {\n const r = await existingCompletion.promise;\n return r as DispatchResult<TOut>;\n }\n }\n }\n }\n\n const jobId = this.newId();\n\n const completion = new Deferred<DispatchResult<unknown>>();\n this.completions.set(jobId, completion);\n\n const lane = opts.overrideLane ? opts.overrideLane : job.type.options.lane;\n const priority = opts.overridePriority !== null ? opts.overridePriority : job.type.options.priority;\n\n const persisted = new PersistedJob({\n id: jobId,\n jobType: jobTypeName,\n inputJson: job.input === undefined ? \"null\" : JSON.stringify(job.input),\n\n state: JobState.Queued,\n lane,\n priority,\n locks: job.type.options.locks,\n\n attempts: 0,\n maxAttempts: job.type.options.maxAttempts,\n nextRunAt: Date.now(),\n\n cancellable: job.type.options.cancellable,\n\n parentId: opts.parentId,\n dedupeKey: opts.dedupeKey,\n\n lastError: null,\n\n createdAt: Date.now(),\n updatedAt: Date.now(),\n });\n\n this.jobs.set(jobId, persisted);\n this.queue.push(jobId);\n\n if (opts.dedupeKey) this.dedupeIndex.set(opts.dedupeKey, jobId);\n\n this.emitJobEvent(persisted, JobState.Queued, null, null);\n await this.persist();\n\n this.wake();\n\n const result = await completion.promise;\n return result as DispatchResult<TOut>;\n }\n\n /* ------------------------\n Scheduler loop safety\n ------------------------- */\n\n private async loopGuarded(): Promise<void> {\n while (!this.stopping) {\n try {\n await this.loopOnce();\n } catch (err) {\n this.notifier.error(`Engine loop error: ${String(err)}`, { scope: NotifyScope.System });\n // prevent spin on repeated bug\n await new Promise<void>((resolve) => setTimeout(resolve, 250));\n }\n }\n }\n\n private async loopOnce(): Promise<void> {\n let dispatchedCount = 0;\n\n while (true) {\n const jobId = this.pickNextRunnable();\n if (!jobId) break;\n dispatchedCount += 1;\n\n // IMPORTANT: never await job execution in the loop\n void this.runJobSafe(jobId);\n }\n\n if (dispatchedCount === 0) {\n await this.wakePromise;\n this.wakePromise = this.resetWake();\n }\n }\n\n private async runJobSafe(jobId: string): Promise<void> {\n try {\n await this.runJobInternal(jobId);\n } catch (err) {\n // This should never happen; keep engine alive anyway.\n this.notifier.error(`runJobInternal crashed: ${String(err)}`, { scope: NotifyScope.System });\n\n const completion = this.completions.get(jobId);\n if (completion) completion.resolve(DispatchResult.failure(new Error(String(err))));\n } finally {\n this.wake();\n }\n }\n\n private pickNextRunnable(): string | null {\n const t = Date.now();\n\n let bestId: string | null = null;\n let bestPriority = Number.NEGATIVE_INFINITY;\n let bestNextRun = Number.POSITIVE_INFINITY;\n\n for (const id of this.queue) {\n const job = this.jobs.get(id);\n if (!job) continue;\n if (job.state !== JobState.Queued) continue;\n\n // Stop policy: only \"console\" lane jobs can run while stopping\n if (this.stopping && job.lane !== \"console\") continue;\n\n if (job.nextRunAt > t) continue;\n if (!this.canRunInLane(job.lane)) continue;\n if (!this.canAcquireLocks(job)) continue;\n\n if (job.priority > bestPriority || (job.priority === bestPriority && job.nextRunAt < bestNextRun)) {\n bestPriority = job.priority;\n bestNextRun = job.nextRunAt;\n bestId = id;\n }\n }\n\n if (!bestId) return null;\n\n const idx = this.queue.indexOf(bestId);\n if (idx >= 0) this.queue.splice(idx, 1);\n\n return bestId;\n }\n\n private canRunInLane(laneName: string): boolean {\n const lane = this.lanes.get(laneName);\n if (!lane) return false;\n const active = this.laneActive.get(laneName);\n if (active === undefined) return false;\n return active < lane.concurrency;\n }\n\n private canAcquireLocks(job: PersistedJob): boolean {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (!holder) continue;\n if (holder === job.id) continue;\n if (job.parentId && holder === job.parentId) continue; // child allowed under parent lock\n return false;\n }\n return true;\n }\n\n private acquireLocks(job: PersistedJob): void {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (!holder) this.locksHeldBy.set(lock, job.id);\n }\n }\n\n private releaseLocks(job: PersistedJob): void {\n for (const lock of job.locks) {\n const holder = this.locksHeldBy.get(lock);\n if (holder === job.id) this.locksHeldBy.delete(lock);\n }\n }\n\n /* ------------------------\n Job execution\n ------------------------- */\n\n private async runJobInternal(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) return;\n\n const jobType = this.registry.get(job.jobType);\n if (!jobType) {\n this.completeFailure(jobId, new Error(`No registered JobType: ${job.jobType}`));\n return;\n }\n\n const laneActive = this.laneActive.get(job.lane);\n if (laneActive === undefined) {\n this.completeFailure(jobId, new Error(`Unknown lane: ${job.lane}`));\n return;\n }\n\n const ctrl = new AbortController();\n this.jobAbort.set(jobId, ctrl);\n\n if (job.cancellable) {\n const engineSignal = this.engineAbort.signal;\n if (engineSignal.aborted) ctrl.abort(engineSignal.reason instanceof Error ? engineSignal.reason : new Error(\"Stopped\"));\n else {\n engineSignal.addEventListener(\n \"abort\",\n () => ctrl.abort(engineSignal.reason instanceof Error ? engineSignal.reason : new Error(\"Stopped\")),\n { once: true }\n );\n }\n }\n\n this.laneActive.set(job.lane, laneActive + 1);\n this.acquireLocks(job);\n\n job.state = JobState.Running;\n job.updatedAt = Date.now();\n await this.persist();\n this.emitJobEvent(job, JobState.Running, null, null);\n\n const ctx = new JobContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: ctrl.signal,\n dispatch: async <TIn, TOut>(call: JobCall<TIn, TOut>, opts: DispatchOptions) => this.dispatch(call, opts),\n });\n\n try {\n const parsed = JSON.parse(job.inputJson) as unknown;\n const input = parsed === null ? undefined : parsed;\n const output = await (jobType as JobType<unknown, unknown>).run(input, ctx);\n\n job.state = JobState.Succeeded;\n job.updatedAt = Date.now();\n job.lastError = null;\n\n await this.persist();\n this.emitJobEvent(job, JobState.Succeeded, null, null);\n\n this.completeSuccess(jobId, output);\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Unknown error\");\n\n job.attempts += 1;\n job.updatedAt = Date.now();\n job.lastError = err.message;\n\n const aborted = ctrl.signal.aborted;\n if (aborted) {\n job.state = JobState.Failed;\n await this.persist();\n this.emitJobEvent(job, JobState.Failed, err.message, null);\n this.notifier.error(`Job ${job.jobType} (${jobId.substring(0, 8)}) cancelled: ${err.message}`);\n this.completeCancelled(jobId, err);\n } else {\n const canRetry = job.attempts < job.maxAttempts && !this.stopping;\n if (canRetry) {\n const delay = backoffMs(job.attempts);\n job.state = JobState.Queued;\n job.nextRunAt = Date.now() + delay;\n await this.persist();\n\n this.queue.push(job.id);\n this.emitJobEvent(job, JobState.Queued, err.message, job.nextRunAt);\n this.notifier.warn(`Job ${job.jobType} (${jobId.substring(0, 8)}) failed, retrying in ${delay}ms (attempt ${job.attempts}/${job.maxAttempts}): ${err.message}`);\n } else {\n job.state = JobState.Failed;\n await this.persist();\n this.emitJobEvent(job, JobState.Failed, err.message, null);\n this.notifier.error(`Job ${job.jobType} (${jobId.substring(0, 8)}) failed after ${job.attempts} attempt(s): ${err.message}`);\n this.completeFailure(jobId, err);\n }\n }\n } finally {\n this.releaseLocks(job);\n\n const currentActive = this.laneActive.get(job.lane);\n if (currentActive !== undefined) this.laneActive.set(job.lane, Math.max(0, currentActive - 1));\n\n this.jobAbort.delete(jobId);\n this.wake();\n }\n }\n\n /* ------------------------\n Orchestrators\n ------------------------- */\n\n private async startOrchestratorsSafe(): Promise<void> {\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n for (const orch of this.orchestrators) {\n Promise.resolve()\n .then(() => orch.onStart?.(ctx))\n .then(() => orch.onStarted?.(ctx))\n .catch((err) => this.notifier.error(`Orchestrator start failed (${orch.name}): ${String(err)}`, { scope: NotifyScope.System }));\n }\n }\n\n private async stopOrchestratorsSafe(): Promise<void> {\n const ctx = new OrchestratorContext({\n engine: this,\n bus: this.bus,\n logger: this.logger,\n notifier: this.notifier,\n flags: this.runtime.flags,\n signal: this.orchestratorAbort.signal,\n });\n\n for (let i = this.orchestrators.length - 1; i >= 0; i--) {\n const orch = this.orchestrators[i];\n try {\n await orch.onStop?.(ctx);\n orch.onStopped?.(ctx);\n } catch (err) {\n this.notifier.error(`Orchestrator stop failed (${orch.name}): ${String(err)}`, { scope: NotifyScope.System });\n }\n\n const subs = this.orchestratorSubscriptions.get(orch.name);\n if (subs) {\n for (const s of subs) s.unsubscribe();\n this.orchestratorSubscriptions.delete(orch.name);\n }\n }\n }\n\n /* ------------------------\n Completion + events + persistence\n ------------------------- */\n\n private emitJobEvent(job: PersistedJob, state: JobState, error: string | null, nextRunAt: number | null): void {\n this.bus.emit(\n \"job:event\",\n new JobEvent({\n ts: Date.now(),\n jobId: job.id,\n jobType: job.jobType,\n state,\n attempt: job.attempts,\n maxAttempts: job.maxAttempts,\n lane: job.lane,\n priority: job.priority,\n error,\n nextRunAt,\n })\n );\n }\n\n private completeSuccess(jobId: string, output: unknown): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.success(output));\n }\n\n private completeFailure(jobId: string, err: Error): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.failure(err));\n }\n\n private completeCancelled(jobId: string, err: Error): void {\n const d = this.completions.get(jobId);\n if (!d) return;\n d.resolve(DispatchResult.cancelled(err));\n }\n\n private async persist(): Promise<void> {\n const jobs: Record<string, PersistedJob> = {};\n for (const [id, job] of this.jobs.entries()) jobs[id] = job;\n await this.storage.save(new EngineStateFile(jobs));\n }\n\n private wake(): void {\n if (this.wakeFn) this.wakeFn();\n }\n\n private resetWake(): Promise<void> {\n return new Promise<void>((resolve) => {\n this.wakeFn = resolve;\n });\n }\n\n private newId(): string {\n return crypto.randomBytes(8).toString(\"hex\");\n }\n}\n\nfunction backoffMs(attempt: number): number {\n const base = 300;\n const max = 30_000;\n const exp = Math.min(max, base * 2 ** (attempt - 1));\n const jitter = Math.floor(Math.random() * 200);\n return exp + jitter;\n}\n", "export enum DispatchStatus {\n Success = \"success\",\n Failure = \"failure\",\n Cancelled = \"cancelled\",\n }\n \n export enum JobState {\n Queued = \"queued\",\n Running = \"running\",\n Succeeded = \"succeeded\",\n Failed = \"failed\",\n }\n \n export enum LogLevel {\n Info = \"info\",\n Warn = \"warn\",\n Error = \"error\",\n Debug = \"debug\",\n Success = \"success\",\n }\n \n export enum NotifyScope {\n Default = \"default\",\n System = \"system\",\n }\n \n export enum NotifyKind {\n Status = \"status\",\n Info = \"info\",\n Success = \"success\",\n Warning = \"warning\",\n Error = \"error\",\n }\n \n export class RuntimeFlags {\n public debug: boolean;\n \n public constructor(debug: boolean) {\n this.debug = debug;\n }\n }\n \nexport enum EnginePhase {\n Idle = \"idle\",\n Booting = \"booting\",\n Running = \"running\",\n Stopping = \"stopping\",\n}\n \n export class LaneConfig {\n public readonly name: string;\n public readonly concurrency: number;\n \n public constructor(name: string, concurrency: number) {\n this.name = name;\n this.concurrency = concurrency;\n }\n }\n ", "import { DispatchStatus } from \"./types\";\r\n\r\nexport class DispatchResult<TOutput> {\r\n public readonly status: DispatchStatus;\r\n public readonly output: TOutput | null;\r\n public readonly error: Error | null;\r\n\r\n private constructor(status: DispatchStatus, output: TOutput | null, error: Error | null) {\r\n this.status = status;\r\n this.output = output;\r\n this.error = error;\r\n }\r\n\r\n public static success<TOutput>(output: TOutput): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Success, output, null);\r\n }\r\n\r\n public static failure<TOutput>(error: Error): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Failure, null, error);\r\n }\r\n\r\n public static cancelled<TOutput>(error: Error): DispatchResult<TOutput> {\r\n return new DispatchResult<TOutput>(DispatchStatus.Cancelled, null, error);\r\n }\r\n}\r\n\r\nexport class Deferred<T> {\r\n public readonly promise: Promise<T>;\r\n private resolveFn: (value: T) => void;\r\n private rejectFn: (error: Error) => void;\r\n\r\n public constructor() {\r\n this.resolveFn = () => {};\r\n this.rejectFn = () => {};\r\n this.promise = new Promise<T>((resolve, reject) => {\r\n this.resolveFn = resolve;\r\n this.rejectFn = reject;\r\n });\r\n }\r\n\r\n public resolve(value: T): void {\r\n this.resolveFn(value);\r\n }\r\n\r\n public reject(error: Error): void {\r\n this.rejectFn(error);\r\n }\r\n}\r\n", "import { DispatchResult } from \"./result\";\nimport { Logger } from \"./logger\";\nimport { NotifyScope, RuntimeFlags, NotifyKind } from \"./types\";\nimport { Engine, DispatchOptions } from \"./engine\";\nimport { Notifier } from \"./notifier\";\nimport { EngineBus } from \"./eventBus\";\n\nexport class JobTypeOptions {\n public readonly name: string;\n public readonly lane: string;\n public readonly priority: number;\n public readonly locks: readonly string[];\n public readonly maxAttempts: number;\n public readonly cancellable: boolean;\n\n public constructor(params: {\n name: string;\n lane: string;\n priority: number;\n locks: readonly string[];\n maxAttempts: number;\n cancellable: boolean;\n }) {\n this.name = params.name;\n this.lane = params.lane;\n this.priority = params.priority;\n this.locks = params.locks;\n this.maxAttempts = params.maxAttempts;\n this.cancellable = params.cancellable;\n }\n}\n\nexport abstract class JobType<TIn, TOut> {\n public readonly options: JobTypeOptions;\n\n protected constructor(options: JobTypeOptions) {\n this.options = options;\n }\n\n public abstract run(input: TIn, ctx: JobContext): Promise<TOut>;\n}\n\nexport class JobCall<TIn, TOut> {\n public readonly type: JobType<TIn, TOut>;\n public readonly input: TIn;\n\n public constructor(type: JobType<TIn, TOut>, input: TIn) {\n this.type = type;\n this.input = input;\n }\n}\n\nexport class JobContext {\n public readonly bus: EngineBus;\n public readonly logger: Logger;\n public readonly notifier: Notifier;\n public readonly flags: RuntimeFlags;\n public readonly signal: AbortSignal;\n public readonly engine: Engine;\n\n private readonly dispatchFn: <TIn, TOut>(job: JobCall<TIn, TOut>, options: DispatchOptions) => Promise<DispatchResult<TOut>>;\n\n public constructor(params: {\n bus: EngineBus;\n engine: Engine;\n logger: Logger;\n notifier: Notifier;\n flags: RuntimeFlags;\n signal: AbortSignal;\n dispatch: <TIn, TOut>(job: JobCall<TIn, TOut>, options: DispatchOptions) => Promise<DispatchResult<TOut>>;\n }) {\n this.bus = params.bus;\n this.engine = params.engine;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.flags = params.flags;\n this.signal = params.signal;\n this.dispatchFn = params.dispatch;\n }\n\n public dispatch<TIn, TOut>(job: JobCall<TIn, TOut>, options?: DispatchOptions): Promise<DispatchResult<TOut>> {\n const safeOptions = options ? options : new DispatchOptions(null, null, null, null);\n return this.dispatchFn(job, safeOptions);\n }\n}\n", "import { JobState, LogLevel, NotifyScope, NotifyKind } from './types';\nimport { Configuration } from './configuration';\nimport type { ConnectAck, RefreshAccessTokenAck, SessionInitAck, SessionConflictRequest, ToolCallRequest } from '@devicelink-workspace/domain';\n\n\nexport type LogOptions = {\n ts?: number;\n category?: string[]\n};\n\nexport class LogEntry {\n public readonly ts: number;\n public readonly message: string;\n\n public constructor(\n message: string,\n options?: LogOptions,\n ) {\n this.ts = options?.ts ?? Date.now();\n this.message = message;\n }\n}\n\n export type NotifyOptions = {\n ts?: number;\n kind?: NotifyKind;\n scope?: NotifyScope;\n groupKey?: string;\n category?: string[]\n};\n\nexport class NotifyEvent {\n public readonly id: string;\n public readonly ts: number;\n public readonly groupKey?: string;\n public readonly kind: NotifyKind;\n public readonly scope: NotifyScope;\n public readonly message: string;\n public readonly category?: string[]\n\n public constructor(\n message: string,\n options?: NotifyOptions,\n ) {\n this.id = crypto.randomUUID();\n this.ts = options?.ts ?? Date.now();\n this.kind = options?.kind ?? NotifyKind.Info;\n this.scope = options?.scope ?? NotifyScope.Default;\n this.message = message;\n this.groupKey = options?.groupKey;\n this.category = options?.category ?? [];\n }\n}\n\nexport class JobEvent {\n public readonly ts: number;\n public readonly jobId: string;\n public readonly jobType: string;\n public readonly state: JobState;\n public readonly attempt: number;\n public readonly maxAttempts: number;\n public readonly lane: string;\n public readonly priority: number;\n public readonly error: string | null;\n public readonly nextRunAt: number | null;\n\n public constructor(params: {\n ts: number;\n jobId: string;\n jobType: string;\n state: JobState;\n attempt: number;\n maxAttempts: number;\n lane: string;\n priority: number;\n error: string | null;\n nextRunAt: number | null;\n }) {\n this.ts = params.ts;\n this.jobId = params.jobId;\n this.jobType = params.jobType;\n this.state = params.state;\n this.attempt = params.attempt;\n this.maxAttempts = params.maxAttempts;\n this.lane = params.lane;\n this.priority = params.priority;\n this.error = params.error;\n this.nextRunAt = params.nextRunAt;\n }\n}\n\n\n\n/** Shared payloads for WS events */\nexport type WsConnected = { url: string; attempt: number };\nexport type WsDisconnected = { code: number; reason?: string; wasClean?: boolean };\nexport type WsRetrying = { retryInSec: number; attempt: number };\nexport type WsRx = { text: string; bytes?: number };\nexport type WsTx = { text: string; bytes?: number; type?: string };\n\n/** Auth payloads */\nexport type TokensUpdated = {\n accessToken: string;\n refreshToken: string;\n expSec: number | undefined;\n};\n\nexport interface EngineEventMap {\n // core\n log: LogEntry;\n \"notify:event\": NotifyEvent;\n\n // engine lifecycle\n \"engine:started\": number;\n \"engine:stopping\": string;\n \"engine:stopped\": number;\n\n // runtime\n \"runtime:debug:changed\": { enabled: boolean };\n\n // console\n \"console:command\": string;\n\n // config (standard)\n \"config:loaded\": Configuration;\n \"config:cache:validated\": void;\n \"config:save:requested\": Configuration;\n \"config:saved\": void;\n\n // ws transport (standard)\n \"ws:connecting\": { url: string; attempt: number };\n \"ws:connected\": WsConnected;\n \"ws:disconnected\": WsDisconnected;\n \"ws:disconnect\": { reason?: string };\n \"ws:retrying\": WsRetrying;\n \"ws:rx\": WsRx;\n \"ws:tx\": WsTx;\n\n // auth protocol state machine (typed)\n \"auth:signin:requested\": void;\n \"auth:signin:completed\": void;\n \"auth:signout:requested\": void;\n \"auth:ws:reconnect\": void;\n \"auth:connect_ack\": ConnectAck;\n \"auth:refresh_ack\": RefreshAccessTokenAck;\n \"auth:session_init_ack\": SessionInitAck;\n \"auth:session_conflict\": SessionConflictRequest;\n \"auth:session_conflict:resolve\": { choice: 'USE_NEW' | 'KEEP_OLD' };\n \"auth:tokens:updated\": TokensUpdated;\n\n \"meta:data:requested:tools\": void;\n \"meta:data:requested:directories\": void;\n\n // tools\n \"tool:call\": ToolCallRequest;\n\n // ui\n \"ui:initialized\": number;\n\n // job\n \"job:event\": JobEvent;\n}", "import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as crypto from \"node:crypto\";\n\nexport class EngineStateFile {\n public readonly jobs: Record<string, PersistedJob>;\n\n public constructor(jobs: Record<string, PersistedJob>) {\n this.jobs = jobs;\n }\n}\n\nexport class PersistedJob {\n public id: string;\n public jobType: string;\n public inputJson: string;\n\n public state: string;\n public lane: string;\n public priority: number;\n public locks: readonly string[];\n\n public attempts: number;\n public maxAttempts: number;\n\n public nextRunAt: number;\n\n public cancellable: boolean;\n\n public parentId: string | null;\n public dedupeKey: string | null;\n\n public lastError: string | null;\n\n public createdAt: number;\n public updatedAt: number;\n\n public constructor(params: PersistedJob) {\n this.id = params.id;\n this.jobType = params.jobType;\n this.inputJson = params.inputJson;\n\n this.state = params.state;\n this.lane = params.lane;\n this.priority = params.priority;\n this.locks = params.locks;\n\n this.attempts = params.attempts;\n this.maxAttempts = params.maxAttempts;\n\n this.nextRunAt = params.nextRunAt;\n\n this.cancellable = params.cancellable;\n\n this.parentId = params.parentId;\n this.dedupeKey = params.dedupeKey;\n\n this.lastError = params.lastError;\n\n this.createdAt = params.createdAt;\n this.updatedAt = params.updatedAt;\n }\n}\n\nexport interface Storage {\n load(): Promise<EngineStateFile>;\n save(state: EngineStateFile): Promise<void>;\n}\n\nexport class JsonFileStorage implements Storage {\n private readonly filePath: string;\n\n public constructor(dir: string, fileName: string) {\n this.filePath = path.join(dir, fileName);\n }\n\n public async load(): Promise<EngineStateFile> {\n try {\n const raw = await fs.readFile(this.filePath, \"utf8\");\n const parsed = JSON.parse(raw) as { jobs: Record<string, PersistedJob> };\n const jobs = parsed.jobs ? parsed.jobs : {};\n return new EngineStateFile(jobs);\n } catch {\n return new EngineStateFile({});\n }\n }\n\n public async save(state: EngineStateFile): Promise<void> {\n await fs.mkdir(path.dirname(this.filePath), { recursive: true });\n const tmp = this.filePath + \".tmp\";\n const raw = JSON.stringify(state, null, 2);\n await fs.writeFile(tmp, raw, \"utf8\");\n await fs.rename(tmp, this.filePath);\n }\n}\n\nexport class MemoryStorage implements Storage {\n private state: EngineStateFile;\n\n public constructor(initial?: EngineStateFile) {\n this.state = initial ?? new EngineStateFile({});\n }\n\n public async load(): Promise<EngineStateFile> {\n // Return a deep copy so callers can't mutate internal reference accidentally\n return new EngineStateFile(structuredClone(this.state.jobs));\n }\n\n public async save(state: EngineStateFile): Promise<void> {\n // Store a deep copy\n this.state = new EngineStateFile(structuredClone(state.jobs));\n }\n}\n", "import { Engine } from \"./engine\";\nimport { EngineBus } from \"./eventBus\";\nimport { Logger } from \"./logger\";\nimport { RuntimeFlags } from \"./types\";\nimport { EngineEventMap } from \"./events\";\nimport { Subscription } from \"./eventBus\";\nimport { Notifier } from \"./notifier\";\n\nexport class OrchestratorContext {\n public readonly engine: Engine;\n public readonly bus: EngineBus;\n public readonly logger: Logger;\n public readonly notifier: Notifier;\n public readonly flags: RuntimeFlags;\n public readonly signal: AbortSignal;\n\n public constructor(params: {\n engine: Engine;\n bus: EngineBus;\n logger: Logger;\n notifier: Notifier;\n flags: RuntimeFlags;\n signal: AbortSignal;\n }) {\n this.engine = params.engine;\n this.bus = params.bus;\n this.logger = params.logger;\n this.notifier = params.notifier;\n this.flags = params.flags;\n this.signal = params.signal;\n }\n\n public on<K extends keyof EngineEventMap>(event: K, handler: (payload: EngineEventMap[K]) => void): Subscription {\n return this.bus.on(event, handler);\n }\n\n}\n\ntype HandlerMap<TEvents> = {\n [K in keyof TEvents]?: (payload: TEvents[K], ctx: OrchestratorContext) => void | Promise<void>;\n};\n\nexport interface Orchestrator {\n readonly name: string;\n \n\n onRegister?(ctx: OrchestratorContext): void;\n\n onStart?(ctx: OrchestratorContext): Promise<void>;\n\n onStarted?(ctx: OrchestratorContext): Promise<void>;\n\n onStop?(ctx: OrchestratorContext): Promise<void>;\n\n onStopped?(ctx: OrchestratorContext): Promise<void>;\n\n handlers?(): HandlerMap<EngineEventMap>;\n}\n", "import { ConfigLoader } from \"../utils/config.builder\";\n\nexport type Directory = {\n id: string;\n name: string;\n path: string;\n tag: string;\n}\n\nexport type Device = {\n id: string;\n name: string;\n tag: string;\n keys: {\n public: string;\n };\n}\n\nexport type Tokens = {\n accessTokenExpSec?: number;\n}\n\nexport class Configuration {\n version: number = 1;\n controlBaseUrl?: string;\n bridgeWsUrl?: string;\n directories: Directory[];\n device?: Device;\n tokens?: Tokens;\n\n public constructor() {\n this.directories = [];\n }\n}\n\nexport class ConfigurationContext {\n public _configuration: Configuration;\n public readonly loader: ConfigLoader;\n\n public get configuration(): Configuration {\n return this._configuration;\n }\n\n public constructor(configuration: Configuration, loader: ConfigLoader) {\n this._configuration = configuration;\n this.loader = loader;\n }\n\n public apply(configuration: Configuration): void {\n this._configuration = configuration;\n }\n}", "import path from 'node:path';\r\nimport os from 'node:os';\r\nimport fs from 'node:fs';\r\nimport { Configuration, Directory, Device, Tokens } from \"../core/configuration\";\r\nimport { ArgvContext } from \"../core/context\";\r\nimport dotenv from 'dotenv';\r\nimport get from 'lodash/get.js';\r\nimport isArray from 'lodash/isArray.js';\r\nimport isObject from 'lodash/isObject.js';\r\nimport isString from 'lodash/isString.js';\r\nimport isEmpty from 'lodash/isEmpty.js';\r\nimport defaultTo from 'lodash/defaultTo.js';\r\nimport { Notifier } from '../core/notifier';\r\nimport { NotifyScope } from '../core/types';\r\nimport { getMachineId } from './machine-id';\r\nimport { KeyBuilder } from './key.builder';\r\nimport { getDirectoryTag, pathToUuidLikeSha256 } from './get-directory-tag';\r\nimport { pathDedupeKey } from '@devicelink-workspace/common';\r\n\r\nconst DEFAULT_CONFIG: Configuration = {\r\n version: 1,\r\n controlBaseUrl: '',\r\n bridgeWsUrl: '',\r\n directories: [],\r\n device: undefined,\r\n};\r\n\r\ntype ProcessEnv = {\r\n [key: string]: string | undefined;\r\n}\r\n\r\nexport class ConfigLoader {\r\n private readonly _notifier: Notifier;\r\n private argv!: ArgvContext;\r\n\r\n private config: Configuration = DEFAULT_CONFIG;\r\n private envFile: dotenv.DotenvConfigOutput = dotenv.config({ quiet: true });\r\n private processEnv: ProcessEnv = {};\r\n private productionEnv: ProcessEnv = {};\r\n private configFileContent: Record<string, unknown> = {};\r\n private _privateKeyCache: string | undefined = undefined;\r\n private _privateKeyToStore: string | undefined = undefined;\r\n\r\n public constructor(notifier: Notifier) {\r\n this._notifier = notifier;\r\n this.loadProductionEnv();\r\n }\r\n\r\n /**\r\n * Load .env.production as the lowest-priority fallback.\r\n * Looks for the file relative to the package root so it works\r\n * both in development (agent/.env.production) and when installed\r\n * from npm (alongside index.js).\r\n */\r\n private loadProductionEnv(): void {\r\n const candidates = [\r\n // npm install: .env.production alongside index.js\r\n path.resolve(path.dirname(process.argv[1] ?? '.'), '.env.production'),\r\n // monorepo dev: agent/.env.production\r\n path.resolve(process.cwd(), '.env.production'),\r\n ];\r\n\r\n for (const candidate of candidates) {\r\n try {\r\n if (fs.existsSync(candidate)) {\r\n const result = dotenv.config({ path: candidate, quiet: true });\r\n if (result.parsed) {\r\n this.productionEnv = result.parsed;\r\n }\r\n return;\r\n }\r\n } catch {\r\n // Silently continue\r\n }\r\n }\r\n }\r\n\r\n public setPrivateKeyCache(value: string | undefined): void {\r\n this._privateKeyCache = value;\r\n }\r\n\r\n public getPrivateKeyToStore(): string | undefined {\r\n return this._privateKeyToStore;\r\n }\r\n\r\n public withDefaultConfig(): ConfigLoader {\r\n this.config.version = DEFAULT_CONFIG.version;\r\n this.config.controlBaseUrl = DEFAULT_CONFIG.controlBaseUrl;\r\n this.config.bridgeWsUrl = DEFAULT_CONFIG.bridgeWsUrl;\r\n this.config.directories = DEFAULT_CONFIG.directories;\r\n this.config.device = DEFAULT_CONFIG.device;\r\n return this;\r\n }\r\n\r\n public withProcessEnv(): ConfigLoader {\r\n this.processEnv = {\r\n NODE_ENV: process.env['NODE_ENV'],\r\n APPDATA: process.env['APPDATA'],\r\n npm_package_version: process.env['npm_package_version'],\r\n };\r\n return this;\r\n }\r\n\r\n public withArgv(argv: ArgvContext): ConfigLoader {\r\n this.argv = argv;\r\n return this;\r\n }\r\n\r\n public withEnviromentFile(filePath: string): ConfigLoader {\r\n this.envFile = dotenv.config({ path: filePath, quiet: true });\r\n return this;\r\n }\r\n\r\n public withConfigFile(filename: string): ConfigLoader {\r\n try {\r\n const configFolder = this.getApplicationConfigFolder();\r\n const configPath = path.join(configFolder, filename);\r\n if (fs.existsSync(configPath)) {\r\n const raw = fs.readFileSync(configPath, 'utf8');\r\n const parsed = JSON.parse(raw);\r\n if (isObject(parsed) && !isArray(parsed)) {\r\n this.configFileContent = parsed as Record<string, unknown>;\r\n } else {\r\n this._notifier.warn(`Config file ${filename} does not contain a valid object`, { scope: NotifyScope.System });\r\n }\r\n }\r\n } catch (error) {\r\n // Log error but continue - config file is optional\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n this._notifier.warn(`Failed to load config file ${filename}: ${errorMessage}`, { scope: NotifyScope.System });\r\n }\r\n return this;\r\n }\r\n\r\n public build(): Configuration {\r\n // Priority: argv -> env file -> config file -> process env\r\n \r\n // Build controlBaseUrl\r\n this.config.controlBaseUrl = this.getControlBaseUrl();\r\n \r\n // Build bridgeWsUrl\r\n this.config.bridgeWsUrl = this.getBridgeWsUrl();\r\n \r\n // Build directories (array of Directory objects)\r\n this.config.directories = this.getDirectories();\r\n \r\n // Build device (Device object)\r\n this.config.device = this.getDevice();\r\n \r\n // Build tokens (only available from config file)\r\n this.config.tokens = this.getTokens();\r\n \r\n return this.config;\r\n }\r\n\r\n public getConfigValue<T>(key: string, options?: { defaultValue?: T }): T {\r\n const value = this.safeGetConfigValue<T>(key);\r\n if (value === undefined) {\r\n return options?.defaultValue as T;\r\n }\r\n return value;\r\n }\r\n\r\n private getControlBaseUrl(): string | undefined {\r\n // argv -> env file -> config file -> process env -> bundled .env.production\r\n return this.argv?.controlUrl\r\n ?? this.safeGetEnvValue('DLINK_CONTROL_URL')\r\n ?? this.safeGetConfigValue<string>('controlBaseUrl')\r\n ?? this.processEnv['DLINK_CONTROL_URL']\r\n ?? this.productionEnv['DLINK_CONTROL_URL']\r\n ?? undefined;\r\n }\r\n\r\n private getBridgeWsUrl(): string | undefined {\r\n // argv -> env file -> config file -> process env -> bundled .env.production\r\n return this.argv?.bridgeWsUrl\r\n ?? this.safeGetEnvValue('DLINK_BRIDGE_URL')\r\n ?? this.safeGetConfigValue<string>('bridgeWsUrl')\r\n ?? this.processEnv['DLINK_BRIDGE_URL']\r\n ?? this.productionEnv['DLINK_BRIDGE_URL']\r\n ?? undefined;\r\n }\r\n\r\n private getDirectories(): Directory[] {\r\n const collected: Directory[] = [];\r\n\r\n // 1. Always include current working directory (highest priority)\r\n collected.push(this.createDirectoryFromPath(process.cwd()));\r\n\r\n // 2. argv (explicit --root flag)\r\n if (this.argv?.rootPath) {\r\n try {\r\n collected.push(...this.parseDirectoriesFromString(this.argv.rootPath));\r\n } catch {\r\n collected.push(this.createDirectoryFromPath(this.argv.rootPath));\r\n }\r\n }\r\n\r\n // 3. env file\r\n const envDirs = this.safeGetEnvValue('DLINK_DIRECTORIES') ?? this.safeGetEnvValue('DLINK_ROOTS');\r\n if (envDirs) {\r\n try { collected.push(...this.parseDirectoriesFromString(envDirs)); } catch { /* skip */ }\r\n }\r\n\r\n // 4. Saved config file (previously added directories persist across sessions)\r\n const configDirs = this.safeGetConfigValue<unknown>('directories') ?? this.safeGetConfigValue<unknown>('roots');\r\n if (configDirs) {\r\n try { collected.push(...this.parseDirectoriesFromValue(configDirs)); } catch { /* skip */ }\r\n }\r\n\r\n // 5. process env\r\n const processDirs = this.processEnv['DLINK_DIRECTORIES'] ?? this.processEnv['DLINK_ROOTS'];\r\n if (processDirs) {\r\n try { collected.push(...this.parseDirectoriesFromString(processDirs)); } catch { /* skip */ }\r\n }\r\n\r\n // Dedup by normalized absolute path (first occurrence wins)\r\n return this.deduplicateDirectories(collected);\r\n }\r\n\r\n private deduplicateDirectories(dirs: Directory[]): Directory[] {\r\n const seen = new Set<string>();\r\n const result: Directory[] = [];\r\n for (const dir of dirs) {\r\n const key = pathDedupeKey(dir.path);\r\n if (seen.has(key)) continue;\r\n seen.add(key);\r\n result.push(dir);\r\n }\r\n return result;\r\n }\r\n\r\n private getDevice(): Device | undefined {\r\n // Get each field individually with priority: argv -> env file -> config file -> process env\r\n \r\n // Device ID: argv -> env file -> config file -> process env -> machine id\r\n // getDeviceId() already handles machine ID fallback, so no need to try again here\r\n const deviceId = this.getDeviceId();\r\n if (!deviceId) {\r\n this._notifier.warn('No device ID found from any source (argv, env, config, process env, or machine ID)', { scope: NotifyScope.System });\r\n return undefined;\r\n }\r\n \r\n // Device name: argv -> env file -> config file -> process env -> hostname\r\n let deviceName = this.getDeviceName();\r\n if (!deviceName) {\r\n deviceName = os.hostname() || 'Unknown Device';\r\n }\r\n \r\n // Device tag: argv -> env file -> config file -> process env\r\n const deviceTag = this.getDeviceTag();\r\n \r\n // Device keys: argv -> config file -> env file -> process env -> generate (private key also from secret storage cache)\r\n const keyBuilder = new KeyBuilder({\r\n notifier: this._notifier,\r\n argv: this.argv,\r\n envFile: this.envFile,\r\n processEnv: this.processEnv,\r\n configFileContent: this.configFileContent,\r\n getPrivateKey: () => this._privateKeyCache,\r\n });\r\n const { publicKey } = keyBuilder.ensureDeviceKeys();\r\n this._privateKeyToStore = keyBuilder.getLastGeneratedPrivateKey();\r\n \r\n const device: Device = {\r\n id: deviceId,\r\n name: deviceName,\r\n tag: deviceTag || '',\r\n keys: {\r\n public: publicKey,\r\n },\r\n };\r\n \r\n this._notifier.info(`Created device: id=${device.id?.substring(0, 8)}..., name=${device.name}, tag=${device.tag || '(empty)'}`, { scope: NotifyScope.System });\r\n \r\n return device;\r\n }\r\n\r\n private getDeviceId(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env -> machine id\r\n // Note: ArgvContext doesn't have deviceId, so skip argv\r\n \r\n this._notifier.info('Checking env file for DLINK_DEVICE_ID...', { scope: NotifyScope.System });\r\n const envId = this.safeGetEnvValue('DLINK_DEVICE_ID');\r\n if (envId && !isEmpty(envId)) {\r\n this._notifier.info(`Found device ID in env file: ${envId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return envId;\r\n }\r\n \r\n this._notifier.info('Checking config file for deviceId...', { scope: NotifyScope.System });\r\n const configId = this.safeGetConfigValue<string>('deviceId') \r\n ?? get(this.safeGetConfigValue<unknown>('device'), 'id') as string | undefined;\r\n if (configId && !isEmpty(String(configId))) {\r\n this._notifier.info(`Found device ID in config file: ${String(configId).substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return String(configId);\r\n }\r\n \r\n this._notifier.info('Checking process env for DLINK_DEVICE_ID...', { scope: NotifyScope.System });\r\n const processId = this.processEnv['DLINK_DEVICE_ID'];\r\n if (processId && !isEmpty(processId)) {\r\n this._notifier.info(`Found device ID in process env: ${processId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return processId;\r\n }\r\n \r\n // Fallback to machine ID\r\n this._notifier.info('Trying machine ID as fallback...', { scope: NotifyScope.System });\r\n const machineId = getMachineId(true);\r\n if (machineId) {\r\n this._notifier.info(`Using machine ID: ${machineId.substring(0, 8)}...`, { scope: NotifyScope.System });\r\n return machineId;\r\n } else {\r\n this._notifier.error('Failed to get machine ID in getDeviceId()', { scope: NotifyScope.System });\r\n }\r\n \r\n this._notifier.warn('No device ID found in any source', { scope: NotifyScope.System });\r\n return undefined;\r\n }\r\n\r\n private getDeviceName(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env -> hostname\r\n // Note: ArgvContext doesn't have deviceName, so skip argv\r\n \r\n const envName = this.safeGetEnvValue('DLINK_DEVICE_NAME');\r\n if (envName && !isEmpty(envName)) return envName;\r\n \r\n const configName = get(this.safeGetConfigValue<unknown>('device'), 'name') as string | undefined;\r\n if (configName && !isEmpty(String(configName))) return String(configName);\r\n \r\n const processName = this.processEnv['DLINK_DEVICE_NAME'];\r\n if (processName && !isEmpty(processName)) return processName;\r\n \r\n // Fallback to hostname\r\n const hostname = os.hostname();\r\n if (hostname && !isEmpty(hostname)) return hostname;\r\n \r\n return undefined;\r\n }\r\n\r\n private getDeviceTag(): string | undefined {\r\n // Priority: argv -> env file -> config file -> process env\r\n // Note: ArgvContext doesn't have deviceTag, so skip argv\r\n \r\n const envTag = this.safeGetEnvValue('DLINK_DEVICE_TAG');\r\n if (envTag) return envTag;\r\n \r\n const configTag = get(this.safeGetConfigValue<unknown>('device'), 'tag') as string | undefined;\r\n if (configTag) return String(configTag);\r\n \r\n const processTag = this.processEnv['DLINK_DEVICE_TAG'];\r\n if (processTag) return processTag;\r\n \r\n return undefined;\r\n }\r\n\r\n private getTokens(): Tokens | undefined {\r\n // Tokens are only available from config file (as per user requirement)\r\n const configTokens = this.safeGetConfigValue<unknown>('tokens');\r\n if (!configTokens || !isObject(configTokens) || isArray(configTokens)) {\r\n return undefined;\r\n }\r\n \r\n const tokensObj = configTokens as Record<string, unknown>;\r\n const tokens: Tokens = {};\r\n \r\n const accessTokenExpSec = get(tokensObj, 'accessTokenExpSec');\r\n if (typeof accessTokenExpSec === 'number') {\r\n tokens.accessTokenExpSec = accessTokenExpSec;\r\n }\r\n \r\n if (tokens.accessTokenExpSec !== undefined) {\r\n return tokens;\r\n }\r\n \r\n return undefined;\r\n }\r\n\r\n\r\n private safeGetEnvValue(key: string): string | undefined {\r\n try {\r\n return get(this.envFile, `parsed.${key}`) as string | undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private safeGetConfigValue<T>(key: string): T | undefined {\r\n try {\r\n return get(this.configFileContent, key) as T | undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n }\r\n\r\n private parseDirectoriesFromString(value: string): Directory[] {\r\n // Try to parse as JSON first\r\n try {\r\n const parsed = JSON.parse(value);\r\n return this.parseDirectoriesFromValue(parsed);\r\n } catch {\r\n // If not JSON, treat as single path string\r\n return [this.createDirectoryFromPath(value)];\r\n }\r\n }\r\n\r\n private parseDirectoriesFromValue(value: unknown): Directory[] {\r\n if (isArray(value)) {\r\n return value\r\n .map((item) => this.parseDirectoryFromValue(item))\r\n .filter((directory): directory is Directory => directory !== null);\r\n }\r\n \r\n if (isString(value)) {\r\n return [this.createDirectoryFromPath(value)];\r\n }\r\n \r\n // Try to parse as single Directory object\r\n const directory = this.parseDirectoryFromValue(value);\r\n return directory ? [directory] : [];\r\n }\r\n\r\n private parseDirectoryFromValue(value: unknown): Directory | null {\r\n if (isString(value)) {\r\n return this.createDirectoryFromPath(value);\r\n }\r\n \r\n if (isObject(value) && !isArray(value)) {\r\n const obj = value as Record<string, unknown>;\r\n const id = (pathToUuidLikeSha256(get(obj, 'path') as string));\r\n const directoryPath = get(obj, 'path') as string;\r\n const name = defaultTo(\r\n get(obj, 'name'),\r\n directoryPath ? path.basename(directoryPath) : ''\r\n ) as string;\r\n \r\n if (!isEmpty(id) && !isEmpty(directoryPath)) {\r\n const tag = getDirectoryTag(directoryPath);\r\n return { \r\n id: String(id), \r\n name: String(name), \r\n path: String(directoryPath),\r\n tag\r\n };\r\n }\r\n }\r\n \r\n return null;\r\n }\r\n\r\n private createDirectoryFromPath(directoryPath: string): Directory {\r\n const normalizedPath = path.resolve(directoryPath);\r\n const id = pathToUuidLikeSha256(normalizedPath);\r\n const name = path.basename(normalizedPath);\r\n const tag = getDirectoryTag(normalizedPath);\r\n return { id, name, path: normalizedPath, tag };\r\n }\r\n\r\n private getApplicationConfigFolder(): string {\r\n const appData = defaultTo(\r\n this.processEnv['APPDATA'],\r\n path.join(os.homedir(), 'AppData', 'Roaming')\r\n );\r\n return path.join(appData, 'DeviceLink');\r\n }\r\n}", "import { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\nconst nodeMachineId = require('node-machine-id');\n\n/**\n * Get the machine ID synchronously.\n * Uses the original (non-hashed) value by default.\n * @param original - If true, return original value; if false, return hashed value (default: true)\n * @returns Machine ID string, or undefined if retrieval fails\n */\nexport function getMachineId(original: boolean = true): string | undefined {\n try {\n const machineId = nodeMachineId.machineIdSync(original);\n if (machineId && typeof machineId === 'string' && machineId.trim().length > 0) {\n return machineId.trim();\n }\n } catch {\n // Ignore errors\n }\n return undefined;\n}\n", "import path from 'node:path';\nimport os from 'node:os';\nimport fs from 'node:fs';\nimport crypto from 'node:crypto';\nimport { ArgvContext } from '../core/context';\nimport dotenv from 'dotenv';\nimport get from 'lodash/get.js';\nimport isEmpty from 'lodash/isEmpty.js';\nimport { Notifier } from '../core/notifier';\nimport { NotifyScope } from '../core/types';\n\ntype ProcessEnv = {\n [key: string]: string | undefined;\n};\n\nexport type DeviceKeys = {\n publicKey: string;\n privateKey: string;\n};\n\nexport class KeyBuilder {\n private readonly _notifier: Notifier;\n private readonly argv?: ArgvContext;\n private readonly envFile: dotenv.DotenvConfigOutput;\n private readonly processEnv: ProcessEnv;\n private readonly configFileContent: Record<string, unknown>;\n private readonly getPrivateKey?: () => string | undefined;\n private _lastGeneratedPrivateKey?: string;\n\n public constructor(params: {\n notifier: Notifier;\n argv?: ArgvContext;\n envFile: dotenv.DotenvConfigOutput;\n processEnv: ProcessEnv;\n configFileContent: Record<string, unknown>;\n getPrivateKey?: () => string | undefined;\n }) {\n this._notifier = params.notifier;\n this.argv = params.argv;\n this.envFile = params.envFile;\n this.processEnv = params.processEnv;\n this.configFileContent = params.configFileContent;\n this.getPrivateKey = params.getPrivateKey;\n }\n\n /** Private key generated this run (when ensureDeviceKeys generated a new keypair). Caller should persist to secret storage. */\n public getLastGeneratedPrivateKey(): string | undefined {\n const key = this._lastGeneratedPrivateKey;\n this._lastGeneratedPrivateKey = undefined;\n return key;\n }\n\n /**\n * Ensures device keys are available.\n * Priority: argv -> config file -> env file -> process env -> generate new\n * Returns both keys, generating a new keypair if neither is found.\n */\n public ensureDeviceKeys(): DeviceKeys {\n // Try to get keys from various sources\n let privateKey = this.getDevicePrivateKey();\n let publicKey = this.getDevicePublicKey();\n \n // If we have both keys, return them\n if (privateKey && publicKey) {\n return { publicKey, privateKey };\n }\n \n // If we have private key but not public, derive public from private\n if (privateKey && !publicKey) {\n try {\n const privateKeyObj = crypto.createPrivateKey(privateKey);\n const publicKeyObj = crypto.createPublicKey(privateKeyObj);\n publicKey = publicKeyObj.export({ format: 'pem', type: 'spki' }).toString('utf8');\n this._notifier.info('Derived public key from private key', { scope: NotifyScope.System });\n return { publicKey, privateKey };\n } catch (e) {\n this._notifier.warn('Failed to derive public key from private key, generating new keypair', { scope: NotifyScope.System });\n }\n }\n \n // If we have public key but not private, we can't derive private, so generate new\n if (publicKey && !privateKey) {\n this._notifier.warn('Public key found but no private key, generating new keypair', { scope: NotifyScope.System });\n }\n \n // Generate new Ed25519 keypair\n this._notifier.info('Generating new Ed25519 keypair...', { scope: NotifyScope.System });\n const { publicKey: pubKey, privateKey: privKey } = crypto.generateKeyPairSync('ed25519');\n const publicKeyPem = pubKey.export({ format: 'pem', type: 'spki' }).toString('utf8');\n const privateKeyPem = privKey.export({ format: 'pem', type: 'pkcs8' }).toString('utf8');\n this._lastGeneratedPrivateKey = privateKeyPem;\n this._notifier.info('Generated new Ed25519 keypair', { scope: NotifyScope.System });\n return { publicKey: publicKeyPem, privateKey: privateKeyPem };\n }\n\n private getDevicePrivateKey(): string | undefined {\n // Priority: secret storage cache (set by LoadConfig job) -> argv (file) -> env file -> process env (config file no longer used)\n if (this.getPrivateKey) {\n const cached = this.getPrivateKey();\n if (cached && !isEmpty(cached)) {\n this._notifier.info('Using private key from secret storage cache', { scope: NotifyScope.System });\n return cached;\n }\n }\n\n // Check argv first (always a file path)\n if (this.argv?.privateKeyFile) {\n const key = this.loadKeyFromFile(this.argv.privateKeyFile);\n if (key) {\n this._notifier.info(`Found private key from --private-key-file: ${this.argv.privateKeyFile}`, { scope: NotifyScope.System });\n return key;\n } else {\n this._notifier.warn(`Failed to load private key from file: ${this.argv.privateKeyFile}`, { scope: NotifyScope.System });\n }\n }\n \n // Check env file\n const envKey = this.safeGetEnvValue('DLINK_DEVICE_PRIVATE_KEY');\n if (envKey && !isEmpty(envKey)) {\n this._notifier.info('Found private key in env file', { scope: NotifyScope.System });\n return envKey;\n }\n \n // Check process env\n const processKey = this.processEnv['DLINK_DEVICE_PRIVATE_KEY'];\n if (processKey && !isEmpty(processKey)) {\n this._notifier.info('Found private key in process env', { scope: NotifyScope.System });\n return processKey;\n }\n \n return undefined;\n }\n\n private getDevicePublicKey(): string | undefined {\n // Priority: argv (file) -> config file -> env file -> process env\n \n // Check argv first (always a file path)\n if (this.argv?.publicKeyFile) {\n const key = this.loadKeyFromFile(this.argv.publicKeyFile);\n if (key) {\n this._notifier.info(`Found public key from --public-key-file: ${this.argv.publicKeyFile}`, { scope: NotifyScope.System });\n return key;\n } else {\n this._notifier.warn(`Failed to load public key from file: ${this.argv.publicKeyFile}`, { scope: NotifyScope.System });\n }\n }\n \n // Check config file\n const configKey = get(this.safeGetConfigValue<unknown>('device'), 'keys.public') as string | undefined;\n if (configKey && !isEmpty(String(configKey))) {\n this._notifier.info('Found public key in config file', { scope: NotifyScope.System });\n return String(configKey);\n }\n \n // Check env file\n const envKey = this.safeGetEnvValue('DLINK_DEVICE_PUBLIC_KEY');\n if (envKey && !isEmpty(envKey)) {\n this._notifier.info('Found public key in env file', { scope: NotifyScope.System });\n return envKey;\n }\n \n // Check process env\n const processKey = this.processEnv['DLINK_DEVICE_PUBLIC_KEY'];\n if (processKey && !isEmpty(processKey)) {\n this._notifier.info('Found public key in process env', { scope: NotifyScope.System });\n return processKey;\n }\n \n return undefined;\n }\n\n /**\n * Loads a key from a file path.\n * Tries multiple path resolutions:\n * 1. Absolute path or relative to CWD\n * 2. Relative to config directory\n */\n private loadKeyFromFile(filePath: string): string | undefined {\n if (!filePath || isEmpty(filePath)) {\n return undefined;\n }\n \n const configFolder = this.getApplicationConfigFolder();\n const possiblePaths = [\n filePath, // Absolute path or relative to CWD\n path.join(configFolder, filePath), // Relative to config directory\n ];\n \n for (const keyPath of possiblePaths) {\n try {\n const resolvedPath = path.resolve(keyPath);\n if (fs.existsSync(resolvedPath)) {\n const stat = fs.statSync(resolvedPath);\n if (stat.isFile()) {\n const keyContent = fs.readFileSync(resolvedPath, 'utf8').trim();\n if (!isEmpty(keyContent)) {\n this._notifier.info(`Loaded key from file: ${resolvedPath}`, { scope: NotifyScope.System });\n return keyContent;\n } else {\n this._notifier.warn(`Key file is empty: ${resolvedPath}`, { scope: NotifyScope.System });\n }\n } else {\n this._notifier.warn(`Path is not a file: ${resolvedPath}`, { scope: NotifyScope.System });\n }\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this._notifier.warn(`Failed to read key file ${keyPath}: ${errorMsg}`, { scope: NotifyScope.System });\n }\n }\n \n this._notifier.warn(`Key file not found: ${filePath} (tried: ${possiblePaths.join(', ')})`, { scope: NotifyScope.System });\n return undefined;\n }\n\n private safeGetEnvValue(key: string): string | undefined {\n try {\n return get(this.envFile, `parsed.${key}`) as string | undefined;\n } catch {\n return undefined;\n }\n }\n\n private safeGetConfigValue<T>(key: string): T | undefined {\n try {\n return get(this.configFileContent, key) as T | undefined;\n } catch {\n return undefined;\n }\n }\n\n private getApplicationConfigFolder(): string {\n const appData = process.env['APPDATA'] ?? path.join(os.homedir(), 'AppData', 'Roaming');\n return path.join(appData, 'DeviceLink');\n }\n}\n", "import crypto from \"node:crypto\";\n\nfunction canonicalizePath(input: string): string {\n let s = input.trim();\n\n // 1) Unify separators to forward slash (works everywhere)\n s = s.replace(/\\\\/g, \"/\");\n\n // 2) Collapse repeated slashes (but keep leading '//' for UNC-ish paths)\n s = s.replace(/(^\\/\\/+)|\\/{2,}/g, (m, leading) => (leading ? \"//\" : \"/\"));\n\n // 3) Remove trailing slash (except root \"/\" or \"//\")\n if (s.length > 1 && s.endsWith(\"/\")) s = s.replace(/\\/+$/g, \"\");\n if (s === \"\") s = \"/\";\n\n // 4) Normalize Windows drive-letter casing: \"e:\" -> \"E:\"\n // (so e:/x and E:/x match)\n s = s.replace(/^([a-zA-Z]):(?=\\/|$)/, (_, d) => `${String(d).toUpperCase()}:`);\n\n // 5) Resolve \".\" and \"..\" purely by string rules (no filesystem access)\n const isAbs =\n s.startsWith(\"/\") ||\n s.startsWith(\"//\") ||\n /^[A-Z]:\\//.test(s); // \"E:/...\"\n\n const prefix = s.startsWith(\"//\") ? \"//\" : s.startsWith(\"/\") ? \"/\" : \"\";\n\n // For \"E:/a/b\", keep \"E:\" as a prefix token\n let drive = \"\";\n const driveMatch = s.match(/^([A-Z]:)(\\/|$)/);\n if (driveMatch) {\n drive = driveMatch[1];\n s = s.slice(drive.length);\n if (s.startsWith(\"/\")) s = s.slice(1);\n } else {\n s = s.replace(/^\\/+/, \"\"); // remove leading slashes for splitting\n }\n\n const parts = s.split(\"/\").filter(Boolean);\n const stack: string[] = [];\n\n for (const p of parts) {\n if (p === \".\") continue;\n if (p === \"..\") {\n if (stack.length > 0 && stack[stack.length - 1] !== \"..\") {\n stack.pop();\n } else if (!isAbs) {\n // relative path can keep leading \"..\"\n stack.push(\"..\");\n }\n continue;\n }\n stack.push(p);\n }\n\n let out = stack.join(\"/\");\n if (drive) out = `${drive}/${out}`.replace(/\\/+$/g, \"\");\n else if (isAbs) out = `${prefix}${out}`.replace(/\\/+$/g, \"\");\n\n // 6) Final: case normalization (optional but usually desirable)\n // If you want case-sensitive behavior, REMOVE the next line.\n out = out.toLowerCase();\n\n return out;\n}\n\nexport function getDirectoryTag(\n path: string,\n groups: number[] = [3, 3, 3, 3]\n): string {\n const canonical = canonicalizePath(path);\n\n const hash = crypto\n .createHash(\"sha256\")\n .update(canonical, \"utf8\")\n .digest(\"base64url\"); // url-safe\n\n const clean = hash.replace(/[^a-zA-Z0-9]/g, \"\").toLowerCase();\n\n const needed = groups.reduce((a, b) => a + b, 0);\n const padded = clean.length >= needed ? clean : clean.padEnd(needed, clean);\n\n let i = 0;\n return groups.map((len) => padded.slice(i, (i += len))).join(\"-\");\n}\n\nexport function pathToUuidLikeSha256(path: string): string {\n const canonical = canonicalizePath(path);\n\n const hex = crypto.createHash(\"sha256\").update(canonical, \"utf8\").digest(\"hex\");\n // take first 32 hex chars (16 bytes) and format like UUID\n const h = hex.slice(0, 32);\n\n const part1 = h.slice(0, 8);\n const part2 = h.slice(8, 12);\n const part3 = h.slice(12, 16);\n const part4 = h.slice(16, 20);\n const part5 = h.slice(20, 32);\n return `${part1}-${part2}-${part3}-${part4}-${part5}`;\n}\n", "import * as crypto from 'node:crypto';\r\nimport { toCrockfordBase32 } from './format.utils';\r\nimport { formatXXXX } from './string.utils';\r\n\r\n/**\r\n * Compute SHA256 hash of a string (hex format)\r\n */\r\nexport function sha256Hex(s: string): string {\r\n return crypto.createHash('sha256').update(s).digest('hex');\r\n}\r\n\r\n/**\r\n * Generate a canonical fingerprint from public key PEM\r\n * Uses SPKI DER format for consistent hashing regardless of PEM formatting\r\n */\r\nexport function fingerprintFromPublicKeyPem(publicKeyPem: string): string {\r\n const keyObj = crypto.createPublicKey(publicKeyPem);\r\n\r\n if (keyObj.asymmetricKeyType !== 'ed25519') {\r\n throw new Error(`Unexpected key type: ${keyObj.asymmetricKeyType}`);\r\n }\r\n\r\n const spkiDer = keyObj.export({ format: 'der', type: 'spki' }) as Buffer;\r\n const hash = crypto.createHash('sha256').update(spkiDer).digest('base64url');\r\n return hash.slice(0, 16).toUpperCase();\r\n}\r\n\r\n/**\r\n * Generate memorable tag from input and salt\r\n * 16 Crockford base32 chars ~= 80 bits. Collision risk is negligible at your scale.\r\n */\r\nexport function memorableTag(input: string, salt: string): string {\r\n const digest = crypto.createHash('sha256').update(`${salt}|${input}`).digest();\r\n const b32 = toCrockfordBase32(digest);\r\n return formatXXXX(b32);\r\n}\r\n\r\n/**\r\n * Generate a new opaque refresh token\r\n * 32 random bytes base64url => ~43 chars\r\n */\r\nexport function newOpaqueToken(): string {\r\n return crypto.randomBytes(32).toString('base64url');\r\n}\r\n\r\n\r\nexport function signConnect(params: { deviceId: string; ts: number; nonce: string; privateKeyPem: string }): string {\r\n const payload = Buffer.from(`${params.deviceId}|${params.ts}|${params.nonce}`, \"utf8\");\r\n const key = crypto.createPrivateKey(params.privateKeyPem);\r\n const sig = crypto.sign(null, payload, key); // Ed25519\r\n return sig.toString(\"base64\");\r\n}\r\n\r\nexport function signRefresh(params: { deviceId: string; ts: number; nonce: string; refreshToken: string; privateKeyPem: string }): string {\r\n const hash = crypto.createHash(\"sha256\").update(params.refreshToken, \"utf8\").digest(\"hex\");\r\n const payload = Buffer.from(`${params.deviceId}|${params.ts}|${params.nonce}|${hash}`, \"utf8\");\r\n const key = crypto.createPrivateKey(params.privateKeyPem);\r\n const sig = crypto.sign(null, payload, key);\r\n return sig.toString(\"base64\");\r\n}\r\n", "/**\r\n * Sleep/delay utility\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Get current time in seconds (Unix timestamp)\r\n */\r\nexport function nowSec(): number {\r\n return Math.floor(Date.now() / 1000);\r\n}\r\n", "import * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * Display-only: normalize backslashes to forward slashes.\n */\nfunction normalizeSlashes(s: string): string {\n return s.replace(/\\\\/g, \"/\");\n}\n\n/**\n * True if string looks like a Windows drive path (C:, D:, \u2026).\n */\nfunction looksLikeWindowsDrivePath(s: string): boolean {\n return /^[A-Za-z]:[\\\\/]/.test(s) || /^[A-Za-z]:$/.test(s.trim());\n}\n\n/**\n * For regex matching only: normalize Windows paths to use `\\` after drive letter.\n */\nfunction normalizeWindowsSeparatorsForMatch(s: string): string {\n if (!looksLikeWindowsDrivePath(s)) return s;\n return s.replace(/\\//g, \"\\\\\");\n}\n\n/**\n * Replace the user home / profile prefix with `~` for safe display (MCP, APIs).\n *\n * - **Same host as path:** uses `path.relative(homedir, path)` (correct on Windows, Linux, macOS agents).\n * - **Linux controller + Windows paths from agents:** regex redacts `C:\\\\Users\\\\<user>`, case/mixed slashes.\n * - **Unix homes:** `/home/\u2026`, `/Users/\u2026` (macOS), `/usr/home/\u2026` (FreeBSD), `/export/home/\u2026` (some Linux/NFS).\n * - **WSL:** `/mnt/<c>/Users/\u2026` \u2192 `~/\u2026`\n * - **Else:** basename only to avoid leaking full paths.\n */\nexport function toTildeHomePath(absolutePath: string | undefined | null): string | undefined {\n if (absolutePath == null) return undefined;\n const raw = String(absolutePath).trim();\n if (raw === \"\") return undefined;\n\n if (raw.startsWith(\"~\")) {\n return normalizeSlashes(raw);\n }\n\n // 1) Real homedir \u2014 only works when path OS matches server OS.\n // Skip if server is Linux but path looks like Windows (cross-platform agent scenario).\n if (!looksLikeWindowsDrivePath(raw)) {\n try {\n const abs = path.resolve(raw);\n const home = path.resolve(os.homedir());\n const rel = path.relative(home, abs);\n if (!rel.startsWith(\"..\") && !path.isAbsolute(rel)) {\n if (rel === \"\") return \"~\";\n return \"~/\" + normalizeSlashes(rel);\n }\n } catch {\n // continue\n }\n }\n\n const win = normalizeWindowsSeparatorsForMatch(raw);\n\n // 2) Windows user profile: C:\\Users\\<user>\\<rest> (Users folder case-insensitive)\n const winUsers = win.match(/^([A-Za-z]:)\\\\(?:[Uu][Ss][Ee][Rr][Ss])\\\\([^\\\\]+)(\\\\.*)?$/);\n if (winUsers) {\n const rest = (winUsers[3] ?? \"\").replace(/\\\\/g, \"/\");\n return rest ? \"~\" + rest : \"~\";\n }\n\n // 3) WSL: /mnt/c/Users/<user>/...\n const wsl = raw.match(/^\\/mnt\\/[a-z]\\/(?:[Uu][Ss][Ee][Rr][Ss])\\/[^/]+(\\/.*)?$/i);\n if (wsl) {\n const rest = wsl[1] ?? \"\";\n return rest ? \"~\" + normalizeSlashes(rest) : \"~\";\n }\n\n // 4) macOS: /Users/<user>/...\n const mac = raw.match(/^\\/Users\\/[^/]+(\\/.*)?$/);\n if (mac) {\n const rest = mac[1] ?? \"\";\n return rest ? \"~\" + normalizeSlashes(rest) : \"~\";\n }\n\n // 5) Linux typical: /home/<user>/...\n const lin = raw.match(/^\\/home\\/[^/]+(\\/.*)?$/);\n if (lin) {\n const rest = lin[1] ?? \"\";\n return rest ? \"~\" + normalizeSlashes(rest) : \"~\";\n }\n\n // 6) FreeBSD: /usr/home/<user>/...\n const fbsd = raw.match(/^\\/usr\\/home\\/[^/]+(\\/.*)?$/);\n if (fbsd) {\n const rest = fbsd[1] ?? \"\";\n return rest ? \"~\" + normalizeSlashes(rest) : \"~\";\n }\n\n // 7) Some NFS / Solaris-style: /export/home/<user>/...\n const exp = raw.match(/^\\/export\\/home\\/[^/]+(\\/.*)?$/);\n if (exp) {\n const rest = exp[1] ?? \"\";\n return rest ? \"~\" + normalizeSlashes(rest) : \"~\";\n }\n\n try {\n return path.basename(path.resolve(raw));\n } catch {\n return raw.split(/[/\\\\]/).pop() ?? raw;\n }\n}\n", "import * as path from \"node:path\";\n\n/**\n * Whether the current platform uses case-insensitive file paths.\n */\nexport const isCaseInsensitiveFS: boolean = process.platform === \"win32\";\n\n/**\n * Resolve a path to its absolute, normalized form.\n * On Windows this also normalizes drive letter casing and separators.\n */\nexport function normalizePath(p: string): string {\n return path.resolve(p);\n}\n\n/**\n * Return a key suitable for Set/Map deduplication of paths.\n * Case-insensitive on Windows, case-sensitive on Linux/macOS/Unix.\n */\nexport function pathDedupeKey(p: string): string {\n const resolved = path.resolve(p);\n return isCaseInsensitiveFS ? resolved.toLowerCase() : resolved;\n}\n\n/**\n * Check if two paths point to the same location.\n * Handles platform-specific case sensitivity.\n */\nexport function pathsEqual(a: string, b: string): boolean {\n return pathDedupeKey(a) === pathDedupeKey(b);\n}\n\n/**\n * Deduplicate an array of paths, preserving order (first occurrence wins).\n * Handles platform-specific case sensitivity.\n */\nexport function deduplicatePaths(paths: string[]): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const p of paths) {\n const key = pathDedupeKey(p);\n if (seen.has(key)) continue;\n seen.add(key);\n result.push(p);\n }\n return result;\n}\n", "import { EngineEventMap } from \"./events\";\n\nexport interface Subscription {\n unsubscribe(): void;\n}\n\nexport class EventBus<TEvents> {\n private readonly handlers: Map<keyof TEvents, Array<(payload: TEvents[keyof TEvents]) => void>>;\n\n public constructor() {\n this.handlers = new Map();\n }\n\n public on<K extends keyof TEvents>(event: K, handler: (payload: TEvents[K]) => void): Subscription {\n const existing = this.handlers.get(event);\n const list = existing ? existing : [];\n list.push(handler as (payload: TEvents[keyof TEvents]) => void);\n this.handlers.set(event, list);\n\n return {\n unsubscribe: () => {\n const current = this.handlers.get(event);\n if (!current) return;\n const next = current.filter((h) => h !== (handler as (payload: TEvents[keyof TEvents]) => void));\n this.handlers.set(event, next);\n },\n };\n }\n\n public emit<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n const list = this.handlers.get(event);\n if (!list) return;\n for (const h of list) {\n (h as (p: TEvents[K]) => void)(payload);\n }\n }\n}\n\n// convenience alias\nexport type EngineBus = EventBus<EngineEventMap>;\n", "import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { getMachineId } from \"../cli/utils/machine-id.js\";\nimport defaultTo from \"lodash/defaultTo.js\";\n\nconst SALT = \"DeviceLink-SecretStorage-v1\";\nconst IV_LENGTH = 12;\nconst TAG_LENGTH = 16;\nconst KEY_LEN = 32;\nconst SECRETS_FILENAME = \"secrets.enc.json\";\n\nexport type GetResult = { ok: true; value: string } | { ok: false };\n\nexport interface BaseStorage {\n get(key: string): Promise<GetResult>;\n set(key: string, value: string): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nfunction getSecretsPath(): string {\n const appData = defaultTo(\n process.env[\"APPDATA\"],\n path.join(os.homedir(), \"AppData\", \"Roaming\")\n );\n return path.join(appData, \"DeviceLink\", SECRETS_FILENAME);\n}\n\nfunction deriveKey(machineId: string): Buffer {\n return crypto.pbkdf2Sync(\n machineId,\n SALT,\n 100000,\n KEY_LEN,\n \"sha256\"\n );\n}\n\nexport class EncryptedFileStorage implements BaseStorage {\n private readonly secretsPath: string;\n private readonly key: Buffer;\n private cache: Record<string, string> = {};\n private loaded = false;\n\n constructor(secretsPath: string, key: Buffer) {\n this.secretsPath = secretsPath;\n this.key = key;\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await fs.readFile(this.secretsPath, \"utf8\");\n const decrypted = this.decrypt(raw);\n this.cache = JSON.parse(decrypted) as Record<string, string>;\n } catch {\n this.cache = {};\n }\n this.loaded = true;\n }\n\n private async save(): Promise<void> {\n await fs.mkdir(path.dirname(this.secretsPath), { recursive: true });\n const plain = JSON.stringify(this.cache);\n const encrypted = this.encrypt(plain);\n const tmp = this.secretsPath + \".tmp\";\n await fs.writeFile(tmp, encrypted, \"utf8\");\n await fs.rename(tmp, this.secretsPath);\n }\n\n private encrypt(plain: string): string {\n const iv = crypto.randomBytes(IV_LENGTH);\n const cipher = crypto.createCipheriv(\"aes-256-gcm\", this.key, iv, {\n authTagLength: TAG_LENGTH,\n });\n const enc = Buffer.concat([\n cipher.update(plain, \"utf8\"),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n return Buffer.concat([iv, tag, enc]).toString(\"base64url\");\n }\n\n private decrypt(b64: string): string {\n const buf = Buffer.from(b64, \"base64url\");\n const iv = buf.subarray(0, IV_LENGTH);\n const tag = buf.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);\n const enc = buf.subarray(IV_LENGTH + TAG_LENGTH);\n const decipher = crypto.createDecipheriv(\"aes-256-gcm\", this.key, iv, {\n authTagLength: TAG_LENGTH,\n });\n decipher.setAuthTag(tag);\n return decipher.update(enc) + decipher.final(\"utf8\");\n }\n\n async get(key: string): Promise<GetResult> {\n await this.load();\n const value = this.cache[key];\n if (value === undefined) return { ok: false };\n return { ok: true, value };\n }\n\n async set(key: string, value: string): Promise<void> {\n await this.load();\n this.cache[key] = value;\n await this.save();\n }\n\n async delete(key: string): Promise<void> {\n await this.load();\n if (this.cache[key] !== undefined) {\n delete this.cache[key];\n await this.save();\n }\n }\n}\n\n/**\n * Creates the default secret storage (encrypted file under DeviceLink config folder).\n * Uses machine ID for key derivation. No plaintext secrets on disk.\n */\nexport async function createStorage(): Promise<BaseStorage> {\n const machineId = getMachineId(true);\n if (!machineId) {\n throw new Error(\"Secret storage requires machine ID\");\n }\n const key = deriveKey(machineId);\n const secretsPath = getSecretsPath();\n return new EncryptedFileStorage(secretsPath, key);\n}\n", "import fs from \"node:fs/promises\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope, NotifyKind } from \"../core/types\";\nimport { Configuration, ConfigurationContext } from \"../core/configuration\";\nimport { ConfigLoader } from \"../utils/config.builder\";\nimport type { BaseStorage } from \"../../storage/index.js\";\n\nexport class LoadConfigInput { }\n\nexport class LoadConfigOutput {\n public readonly ok: boolean;\n public readonly config: Configuration;\n\n public constructor(ok: boolean, config: Configuration) {\n this.ok = ok;\n this.config = config;\n }\n}\n\nexport class LoadConfigJob extends JobType<LoadConfigInput, LoadConfigOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"load-config\",\n lane: \"main\",\n priority: 1000,\n locks: [\"GLOBAL\"],\n maxAttempts: 3,\n cancellable: true,\n })\n );\n }\n\n public async run(input: LoadConfigInput, ctx: JobContext): Promise<LoadConfigOutput> {\n ctx.notifier.info(\"Loading configuration...\", { scope: NotifyScope.System });\n\n const configLoader = ctx.engine.configurationContext.loader;\n\n const refreshRes = await ctx.engine.secrets.get(\"devicePrivateKey\");\n configLoader.setPrivateKeyCache(refreshRes.ok && refreshRes.value ? refreshRes.value : undefined);\n\n configLoader.withDefaultConfig();\n configLoader.withArgv(ctx.engine.argv);\n\n if (ctx.engine.argv.enviromentFile) {\n configLoader.withEnviromentFile(ctx.engine.argv.enviromentFile);\n }\n configLoader.withConfigFile('config.json');\n configLoader.withProcessEnv();\n const config = configLoader.build();\n\n const privateKeyToStore = configLoader.getPrivateKeyToStore();\n if (privateKeyToStore) {\n await ctx.engine.secrets.set(\"devicePrivateKey\", privateKeyToStore);\n }\n\n this.updateUi(config, ctx);\n\n ctx.notifier.success(\"Configuration loaded\");\n\n ctx.engine.applyConfiguration(config);\n\n ctx.bus.emit(\"config:loaded\", config);\n return new LoadConfigOutput(true, config);\n }\n\n private updateUi(config: Configuration, ctx: JobContext): void {\n const sys = { scope: NotifyScope.System };\n ctx.notifier.info(`Control base URL: ${config.controlBaseUrl}`, sys);\n ctx.notifier.info(`Bridge WebSocket URL: ${config.bridgeWsUrl}`, sys);\n ctx.notifier.info(`Directories: ${config.directories.map(directory => directory.path).join(', ')}`, sys);\n ctx.notifier.info(`Device: ${config.device?.id}`, sys);\n ctx.notifier.info(`Device name: ${config.device?.name}`, sys);\n ctx.notifier.info(`Device tag: ${config.device?.tag}`, sys);\n ctx.notifier.info(`Device keys public: ${config.device?.keys?.public ? '***' : '(none)'}`, sys);\n }\n}\n\nexport const loadConfigJob = new LoadConfigJob();\n\n\nexport function loadConfigCall(input: LoadConfigInput): JobCall<LoadConfigInput, LoadConfigOutput> {\n return new JobCall(loadConfigJob, input);\n}\n\n", "import { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope, NotifyKind } from \"../core/types\";\nimport { ConsoleCommandInput } from \"../utils/command-job.builder\";\n\nexport class ConsoleCommandOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ConsoleCommandJob extends JobType<ConsoleCommandInput, ConsoleCommandOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"console-command\",\n lane: \"console\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(input: ConsoleCommandInput, ctx: JobContext): Promise<ConsoleCommandOutput> {\n ctx.notifier.info(`Executing console command: ${input.kind}`);\n // TODO: Implement actual command handling based on input.kind\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n ctx.notifier.info(`Console command executed: ${input.kind}`);\n ctx.notifier.success(`Console command executed: ${input.kind}`);\n return new ConsoleCommandOutput(true);\n }\n}\n\nexport const consoleCommandJob = new ConsoleCommandJob();\n\n\nexport function consoleCommandCall(input: ConsoleCommandInput): JobCall<ConsoleCommandInput, ConsoleCommandOutput> {\n return new JobCall(consoleCommandJob, input);\n}\n", "import { JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\n\nexport class ContactServerInput {\n public readonly mode: string;\n public constructor(mode: string) {\n this.mode = mode;\n }\n}\n\nexport class ContactServerOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ContactServerJob extends JobType<ContactServerInput, ContactServerOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"contact-server\",\n lane: \"main\",\n priority: 900,\n locks: [\"GLOBAL\"],\n maxAttempts: 8,\n cancellable: true,\n })\n );\n }\n\n public async run(input: ContactServerInput, ctx: JobContext): Promise<ContactServerOutput> {\n ctx.notifier.info(`contact server mode=${input.mode}`, { scope: NotifyScope.System });\n\n // TODO: real connection; respect ctx.signal for cancellation\n await new Promise<void>((resolve) => setTimeout(resolve, 200));\n\n return new ContactServerOutput(true);\n }\n}\n\nexport const contactServerJob = new ContactServerJob();\n", "import { JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\n\nexport class SendServerResultInput {\n public readonly requestId: string;\n public readonly resultJson: string;\n\n public constructor(requestId: string, resultJson: string) {\n this.requestId = requestId;\n this.resultJson = resultJson;\n }\n}\n\nexport class SendServerResultOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class SendServerResultJob extends JobType<SendServerResultInput, SendServerResultOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"send-server-result\",\n lane: \"io\",\n priority: 200,\n locks: [],\n maxAttempts: 10,\n cancellable: true,\n })\n );\n }\n\n public async run(input: SendServerResultInput, ctx: JobContext): Promise<SendServerResultOutput> {\n ctx.notifier.info(`send result requestId=${input.requestId}`, { scope: NotifyScope.System });\n\n // TODO: send via WS outbound channel, respect ctx.signal\n await new Promise<void>((resolve) => setTimeout(resolve, 10));\n\n return new SendServerResultOutput(true);\n }\n}\n\nexport const sendServerResultJob = new SendServerResultJob();\n", "import crypto from \"node:crypto\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../core/job\";\nimport { NotifyScope } from \"../core/types\";\nimport { Api } from \"../api\";\nimport type { FetchError } from \"../api/api.call\";\nimport { signRefresh } from \"@devicelink-workspace/common\";\nimport {\n DeviceAuthRefreshResponse,\n DeviceAuthRefreshSuccessResponse,\n} from \"@devicelink-workspace/domain\";\nimport type { BaseStorage } from \"../../storage/index.js\";\n\n/**\n * If your HTTP handler wraps like { ok:true, data:{...} }\n * this matches the common pattern without using `any`.\n */\ntype WrappedOk = { ok: true; data: DeviceAuthRefreshSuccessResponse };\n\nfunction isWrappedOk(x: unknown): x is WrappedOk {\n if (typeof x !== \"object\" || x === null) return false;\n const r = x as Record<string, unknown>;\n if (r[\"ok\"] !== true) return false;\n const data = r[\"data\"];\n if (typeof data !== \"object\" || data === null) return false;\n\n const d = data as Record<string, unknown>;\n return (\n d[\"ok\"] === true &&\n typeof d[\"access_token\"] === \"string\" &&\n typeof d[\"refresh_token\"] === \"string\" &&\n typeof d[\"expires_in_sec\"] === \"number\" &&\n typeof d[\"device_id\"] === \"string\"\n );\n}\n\nfunction isUnwrappedOk(x: DeviceAuthRefreshResponse): x is DeviceAuthRefreshSuccessResponse {\n return (\n (x as unknown as Record<string, unknown>)[\"ok\"] === true &&\n typeof (x as unknown as Record<string, unknown>)[\"access_token\"] === \"string\"\n );\n}\n\nexport class RefreshTokensInput {\n public constructor(public readonly reason: string) {}\n}\n\n/** Server error codes that mean \"refresh token no longer valid, user must sign in again\" (no retry). */\nexport const REFRESH_UNRECOVERABLE_CODES = ['REFRESH_EXPIRED', 'REFRESH_REVOKED', 'REFRESH_NOT_FOUND'] as const;\n\nexport class RefreshTokensOutput {\n public constructor(\n public readonly ok: boolean,\n public readonly accessToken?: string,\n public readonly refreshToken?: string,\n public readonly expiresInSec?: number,\n public readonly error?: string,\n public readonly retryAfterSec?: number,\n public readonly errorCode?: string\n ) {}\n}\n\nexport class RefreshTokensJob extends JobType<RefreshTokensInput, RefreshTokensOutput> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"refresh-tokens\",\n lane: \"io\",\n priority: 900,\n locks: [\"AUTH_REFRESH\"],\n maxAttempts: 5,\n cancellable: true,\n })\n );\n }\n\n public async run(input: RefreshTokensInput, ctx: JobContext): Promise<RefreshTokensOutput> {\n const cfg = ctx.engine.configurationContext.configuration;\n\n if (!cfg.controlBaseUrl) return new RefreshTokensOutput(false, undefined, undefined, undefined, \"controlBaseUrl missing\");\n if (!cfg.device?.id) return new RefreshTokensOutput(false, undefined, undefined, undefined, \"device.id missing\");\n\n const privateRes = await ctx.engine.secrets.get(\"devicePrivateKey\");\n if (!privateRes.ok || !privateRes.value) {\n return new RefreshTokensOutput(false, undefined, undefined, undefined, \"device private key missing\");\n }\n const privateKeyPem = privateRes.value;\n\n const refreshRes = await ctx.engine.secrets.get(\"refreshToken\");\n if (!refreshRes.ok || !refreshRes.value) {\n return new RefreshTokensOutput(false, undefined, undefined, undefined, \"refresh token missing\");\n }\n const refreshToken = refreshRes.value;\n\n ctx.notifier.info(`Refreshing tokens (job) reason=${input.reason}`, { scope: NotifyScope.System, category: ['token-refresh'] });\n\n const ts = Date.now();\n const nonce = crypto.randomBytes(16).toString(\"base64url\");\n const sig = signRefresh({\n deviceId: cfg.device.id,\n ts,\n nonce,\n refreshToken,\n privateKeyPem,\n });\n\n const api = new Api(cfg, ctx.notifier);\n\n let raw: unknown;\n try {\n raw = await api.deviceAuthRefresh({\n device_id: cfg.device.id,\n refresh_token: refreshToken,\n ts,\n nonce,\n sig,\n });\n } catch (e: unknown) {\n const err = e instanceof Error ? e.message : String(e);\n const fetchErr = e as FetchError;\n const retryAfterSec = fetchErr.retryAfterSec;\n const status = fetchErr.status;\n const body = fetchErr.body as Record<string, unknown> | undefined;\n const errObj = body != null ? (body as Record<string, unknown>)['error'] : undefined;\n const errorCode =\n status === 401 &&\n errObj != null &&\n typeof errObj === 'object' &&\n (errObj as Record<string, unknown>)['code'] === 'REFRESH_NOT_FOUND'\n ? 'REFRESH_NOT_FOUND'\n : undefined;\n if (errorCode === 'REFRESH_NOT_FOUND') {\n ctx.notifier.warn(\n 'Refresh token not found; clearing stored refresh token and stopping automatic refresh. Please run signin.',\n { category: ['token-refresh'] }\n );\n\n // Critical: clear invalid refresh token so we stop retrying forever\n await ctx.engine.secrets.delete('refreshToken').catch(() => {});\n\n return new RefreshTokensOutput(\n false,\n undefined,\n undefined,\n undefined,\n 'Refresh token not found',\n undefined,\n 'REFRESH_NOT_FOUND'\n );\n }\n ctx.notifier.error(`Refresh tokens failed: ${err}`, { category: ['token-refresh'] });\n return new RefreshTokensOutput(false, undefined, undefined, undefined, err, retryAfterSec, errorCode);\n }\n\n const normalized: DeviceAuthRefreshSuccessResponse | null = this.normalizeRefreshResponse(raw);\n\n if (!normalized) {\n const err = this.extractErrorMessage(raw);\n const errorCode = this.extractErrorCode(raw);\n ctx.notifier.error(`Refresh tokens failed: ${err}`, { category: ['token-refresh'] });\n return new RefreshTokensOutput(false, undefined, undefined, undefined, err, undefined, errorCode);\n }\n\n if (normalized.refresh_token) {\n await ctx.engine.secrets.set(\"refreshToken\", normalized.refresh_token);\n }\n\n return new RefreshTokensOutput(true, normalized.access_token, normalized.refresh_token, normalized.expires_in_sec);\n }\n\n private normalizeRefreshResponse(\n raw: unknown\n ): DeviceAuthRefreshSuccessResponse | null {\n // Wrapped controller response\n if (isWrappedOk(raw)) return raw.data;\n\n // Domain response (unwrapped)\n if (this.looksLikeDomainRefresh(raw)) {\n const r = raw as DeviceAuthRefreshResponse;\n if (isUnwrappedOk(r)) return r;\n return null;\n }\n\n return null;\n }\n\n private looksLikeDomainRefresh(raw: unknown): raw is DeviceAuthRefreshResponse {\n if (typeof raw !== \"object\" || raw === null) return false;\n const r = raw as Record<string, unknown>;\n return r[\"ok\"] === true || r[\"ok\"] === false;\n }\n\n private extractErrorMessage(raw: unknown): string {\n if (typeof raw !== \"object\" || raw === null) return \"Unknown error\";\n const r = raw as Record<string, unknown>;\n\n // wrapped error: { ok:false, error:{message} }\n if (r[\"ok\"] === false) {\n const err = r[\"error\"];\n if (typeof err === \"object\" && err !== null) {\n const e = err as Record<string, unknown>;\n const msg = e[\"message\"];\n if (typeof msg === \"string\" && msg.length > 0) return msg;\n }\n }\n\n // wrapped ok but missing data\n if (r[\"ok\"] === true && \"data\" in r) return \"Bad refresh response: missing token fields\";\n\n return \"Unknown error\";\n }\n\n private extractErrorCode(raw: unknown): string | undefined {\n if (typeof raw !== \"object\" || raw === null) return undefined;\n const r = raw as Record<string, unknown>;\n if (r[\"ok\"] !== false) return undefined;\n const err = r[\"error\"];\n if (typeof err !== \"object\" || err === null) return undefined;\n const code = (err as Record<string, unknown>)[\"code\"];\n return typeof code === \"string\" ? code : undefined;\n }\n}\n\nexport const refreshTokensJob = new RefreshTokensJob();\n\nexport function refreshTokensCall(input: RefreshTokensInput): JobCall<RefreshTokensInput, RefreshTokensOutput> {\n return new JobCall(refreshTokensJob, input);\n}\n", "import { Configuration } from '../core/configuration';\r\nimport { Notifier } from '../core/notifier';\r\n\r\nexport type ApiCallContext = {\r\n configuration: Configuration;\r\n notifier: Notifier;\r\n};\r\n\r\ntype Handler<Input, Output> = (\r\n context: ApiCallContext,\r\n input: Input,\r\n) => Promise<Output>;\r\n\r\nexport class ApiCall<Input, Output> {\r\n constructor(\r\n private readonly context: ApiCallContext,\r\n private readonly handler: Handler<Input, Output>,\r\n ) {}\r\n\r\n execute(input: Input): Promise<Output> {\r\n return this.handler(this.context, input);\r\n }\r\n}\r\n\r\nexport type FetchError = Error & {\r\n retryAfterSec?: number;\r\n status?: number;\r\n body?: unknown;\r\n};\r\n\r\nexport async function fetchJson<T>(\r\n context: ApiCallContext,\r\n path: string,\r\n init: RequestInit,\r\n): Promise<T> {\r\n const url = `${context.configuration.controlBaseUrl}${path}`;\r\n const res = await fetch(url, init);\r\n\r\n if (!res.ok) {\r\n const text = await res.text().catch(() => '');\r\n const err = new Error(`HTTP ${res.status}: ${text}`) as FetchError;\r\n err.status = res.status;\r\n try {\r\n err.body = text ? (JSON.parse(text) as unknown) : undefined;\r\n } catch {\r\n err.body = undefined;\r\n }\r\n if (res.status === 429) {\r\n const retryAfter = res.headers.get('Retry-After');\r\n if (retryAfter !== null) {\r\n const sec = parseInt(retryAfter, 10);\r\n if (Number.isFinite(sec) && sec >= 0) err.retryAfterSec = sec;\r\n }\r\n }\r\n throw err;\r\n }\r\n\r\n return res.json() as Promise<T>;\r\n}\r\n", "import { z } from 'zod';\nimport { ApiCall, ApiCallContext, fetchJson } from '../api.call';\nimport type { DeviceAuthStartRequest, DeviceAuthStartResponse } from '@devicelink-workspace/domain';\n\nexport function makeDeviceAuthStart(context: ApiCallContext) {\n return new ApiCall<DeviceAuthStartRequest, DeviceAuthStartResponse>(\n context,\n async (c, input) => {\n return fetchJson<DeviceAuthStartResponse>(c, '/api/device/authorize/start', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n });\n },\n );\n}\n", "import { z } from 'zod';\nimport { ApiCall, ApiCallContext, fetchJson } from '../api.call';\nimport type { DeviceAuthProveRequest, DeviceAuthProveResponse } from '@devicelink-workspace/domain';\n\nexport function makeDeviceAuthProve(context: ApiCallContext) {\n return new ApiCall<DeviceAuthProveRequest, DeviceAuthProveResponse>(\n context,\n async (c, input) => {\n return fetchJson<DeviceAuthProveResponse>(c, '/api/device/authorize/prove', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n });\n },\n );\n}\n", "import { ApiCall, ApiCallContext } from \"../api.call\";\nimport { NotifyScope } from \"../../core/types\";\nimport { z } from \"zod\";\nimport type {\n DeviceAuthStreamRequest,\n DeviceAuthStreamResponse,\n} from \"@devicelink-workspace/domain\";\n\nconst DeviceAuthStreamResponseSchema = z.union([\n z.object({\n status: z.literal(\"pending\"),\n needs_proof: z.boolean(),\n }),\n z.object({\n status: z.literal(\"approved\"),\n needs_proof: z.boolean(),\n }),\n z.object({\n error: z.literal(\"access_denied\"),\n }),\n z.object({\n error: z.literal(\"expired_token\"),\n }),\n]);\n\n/**\n * makeDeviceAuthStream\n * Waits for SSE events from Control. Returns only status snapshots/errors:\n * - pending: { status: \"pending\", needs_proof: boolean }\n * - approved: { status: \"approved\", needs_proof: boolean }\n * - denied: { error: \"access_denied\" }\n * - expired: { error: \"expired_token\" }\n */\nexport function makeDeviceAuthStream(context: ApiCallContext) {\n return new ApiCall<DeviceAuthStreamRequest, DeviceAuthStreamResponse>(\n context,\n async (c, input) => {\n const url = new URL(\"/api/device/authorize/stream\", c.configuration.controlBaseUrl);\n url.searchParams.set(\"device_code\", input.deviceCode);\n const notifier = c.notifier;\n\n const controller = new AbortController();\n const t = setTimeout(() => {\n notifier.error(`[deviceAuthStream] Timeout reached, aborting`);\n controller.abort();\n }, Math.max(1000, input.timeoutMs));\n\n if (input.signal) {\n input.signal.addEventListener(\"abort\", () => {\n notifier.warn(\n `[deviceAuthStream] External signal aborted: ${String((input.signal as any)?.reason ?? \"\")}`,\n );\n controller.abort();\n });\n }\n\n try {\n const res = await fetch(url.toString(), {\n method: \"GET\",\n headers: { Accept: \"text/event-stream\" },\n signal: controller.signal,\n });\n\n if (!res.ok || !res.body) {\n const text = await res.text().catch(() => \"\");\n notifier.error(\n `[deviceAuthStream] Response error: ${res.status} - ${text}`,\n );\n throw new Error(`device/authorize/stream failed (${res.status}): ${text}`);\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder(\"utf-8\");\n let buf = \"\";\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n notifier.error(`[deviceAuthStream] Stream ended unexpectedly`);\n break;\n }\n\n buf += decoder.decode(value, { stream: true });\n\n while (true) {\n const idx = buf.indexOf(\"\\n\\n\");\n if (idx === -1) break;\n\n const raw = buf.slice(0, idx);\n buf = buf.slice(idx + 2);\n\n let event: string | null = null;\n let dataStr: string | null = null;\n\n for (const line of raw.split(\"\\n\")) {\n if (line.startsWith(\"event:\")) event = line.slice(6).trim();\n if (line.startsWith(\"data:\")) dataStr = line.slice(5).trim();\n }\n\n // ignore keepalive / comments etc\n if (!event || !dataStr) continue;\n\n let data: unknown;\n try {\n data = JSON.parse(dataStr);\n } catch (e) {\n notifier.error(\n `[deviceAuthStream] Failed to parse event data as JSON: ${String(e)}`,\n );\n continue;\n }\n\n const parsed = DeviceAuthStreamResponseSchema.safeParse(data);\n if (!parsed.success) {\n notifier.error(\n `[deviceAuthStream] Event validation failed (${event}): ${String(parsed.error)}`,\n );\n continue;\n }\n\n const payload = parsed.data;\n\n // terminal events:\n if (event === \"approved\") return payload;\n if (event === \"denied\") return payload;\n if (event === \"expired\") return payload;\n\n // pending is non-terminal; you can log only if needs_proof is true\n if (event === \"pending\") {\n if ((payload as any)?.status === \"pending\" && (payload as any)?.needs_proof === true) {\n notifier.warn(\n `[deviceAuthStream] pending: needs_proof=true (unexpected before approval)`,\n );\n }\n continue;\n }\n\n notifier.warn(`[deviceAuthStream] Unknown event type: ${event}`);\n }\n }\n\n notifier.error(\n `[deviceAuthStream] Stream ended unexpectedly without completion`,\n );\n throw new Error(\"Device authorization stream ended without completion\");\n } catch (e: any) {\n if (e?.name === \"AbortError\") {\n notifier.warn(`[deviceAuthStream] Aborted: ${e?.message ?? \"\"}`);\n } else {\n notifier.error(`[deviceAuthStream] Error: ${e?.message ?? String(e)}`);\n }\n throw e;\n } finally {\n clearTimeout(t);\n }\n },\n );\n}\n", "import { ApiCall, ApiCallContext, fetchJson } from \"../api.call\";\r\nimport type { DeviceAuthTokenRequest, DeviceAuthTokenResponse } from \"@devicelink-workspace/domain\";\r\n\r\nexport function makeDeviceAuthToken(context: ApiCallContext) {\r\n return new ApiCall<DeviceAuthTokenRequest, DeviceAuthTokenResponse>(\r\n context,\r\n async (c, input) => {\r\n return fetchJson<DeviceAuthTokenResponse>(c, \"/api/device/authorize/token\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(input),\r\n });\r\n },\r\n );\r\n}\r\n", "import { ApiCall, ApiCallContext, fetchJson } from \"../api.call\";\r\nimport {\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse,\r\n} from \"@devicelink-workspace/domain\";\r\n\r\nexport function makeDeviceAuthRefresh(context: ApiCallContext) {\r\n return new ApiCall<DeviceAuthRefreshRequest, DeviceAuthRefreshResponse>(\r\n context,\r\n async (c, input) => {\r\n const controller = new AbortController();\r\n const timeoutMs = 30_000; // 30 second timeout\r\n const timeoutId = setTimeout(() => {\r\n controller.abort();\r\n }, timeoutMs);\r\n\r\n try {\r\n const result = await fetchJson<DeviceAuthRefreshResponse>(c, \"/api/device/authorize/refresh\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(input),\r\n signal: controller.signal,\r\n });\r\n clearTimeout(timeoutId);\r\n return result;\r\n } catch (error: unknown) {\r\n clearTimeout(timeoutId);\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new Error(`Refresh token request timed out after ${timeoutMs}ms`);\r\n }\r\n throw error;\r\n }\r\n }\r\n );\r\n}\r\n", "import { ApiCall } from './api.call';\r\nimport { makeDeviceAuthStart } from './definitions/device-auth-start.api';\r\nimport { makeDeviceAuthProve } from './definitions/device-auth-prove.api';\r\nimport { makeDeviceAuthStream } from './definitions/device-auth-stream.api';\r\nimport { makeDeviceAuthToken } from './definitions/device-auth-token.api';\r\nimport { Configuration } from '../core/configuration';\r\nimport { Notifier } from '../core/notifier';\r\nimport {\r\n DeviceAuthProveRequest,\r\n DeviceAuthProveResponse,\r\n DeviceAuthStartRequest,\r\n DeviceAuthStartResponse,\r\n DeviceAuthStreamRequest,\r\n DeviceAuthStreamResponse,\r\n DeviceAuthTokenRequest,\r\n DeviceAuthTokenResponse,\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse,\r\n} from '@devicelink-workspace/domain';\r\nimport { makeDeviceAuthRefresh } from './definitions/device-auth-refresh.api';\r\n\r\nexport class Api {\r\n private readonly deviceAuthStartCall: ApiCall<\r\n DeviceAuthStartRequest,\r\n DeviceAuthStartResponse\r\n >;\r\n private readonly deviceAuthProveCall: ApiCall<\r\n DeviceAuthProveRequest,\r\n DeviceAuthProveResponse\r\n >;\r\n private readonly deviceAuthStreamCall: ApiCall<\r\n DeviceAuthStreamRequest,\r\n DeviceAuthStreamResponse\r\n >;\r\n private readonly deviceAuthTokenCall: ApiCall<\r\n DeviceAuthTokenRequest,\r\n DeviceAuthTokenResponse\r\n >;\r\n private readonly deviceAuthRefreshCall: ApiCall<\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse\r\n >;\r\n\r\n constructor(configuration: Configuration, notifier: Notifier) {\r\n const context = { configuration, notifier };\r\n this.deviceAuthStartCall = makeDeviceAuthStart(context);\r\n this.deviceAuthProveCall = makeDeviceAuthProve(context);\r\n this.deviceAuthStreamCall = makeDeviceAuthStream(context);\r\n this.deviceAuthTokenCall = makeDeviceAuthToken(context);\r\n this.deviceAuthRefreshCall = makeDeviceAuthRefresh(context);\r\n }\r\n\r\n deviceAuthStart(input: DeviceAuthStartRequest) {\r\n return this.deviceAuthStartCall.execute(input);\r\n }\r\n\r\n deviceAuthProve(input: DeviceAuthProveRequest) {\r\n return this.deviceAuthProveCall.execute(input);\r\n }\r\n\r\n deviceAuthStream(input: DeviceAuthStreamRequest) {\r\n return this.deviceAuthStreamCall.execute(input);\r\n }\r\n\r\n deviceAuthToken(input: DeviceAuthTokenRequest) {\r\n return this.deviceAuthTokenCall.execute(input);\r\n }\r\n \r\n deviceAuthRefresh(input: DeviceAuthRefreshRequest) {\r\n return this.deviceAuthRefreshCall.execute(input);\r\n }\r\n}\r\n", "import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\r\nimport { Subscription } from \"../core/eventBus.js\";\r\nimport { LogEntry, JobEvent, NotifyEvent } from \"../core/events.js\";\r\n\r\nexport class TelemetryOrchestrator implements Orchestrator {\r\n public readonly name: string;\r\n\r\n private readonly filePath: string;\r\n\r\n private readonly buffer: string[];\r\n private timer: NodeJS.Timeout | null;\r\n\r\n private subs: Subscription[];\r\n\r\n public constructor(filePath: string) {\r\n this.name = \"telemetry-orchestrator\";\r\n this.filePath = filePath;\r\n\r\n this.buffer = [];\r\n this.timer = null;\r\n this.subs = [];\r\n }\r\n\r\n public onRegister(_ctx: OrchestratorContext): void {}\r\n\r\n public async onStart(ctx: OrchestratorContext): Promise<void> {\r\n this.subs.push(ctx.on(\"log\", (e) => this.onLog(e)));\r\n this.subs.push(ctx.on(\"job:event\", (e) => this.onJob(e)));\r\n this.subs.push(ctx.on(\"notify:event\", (e) => this.onNotify(e)));\r\n }\r\n\r\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\r\n return Promise.resolve();\r\n }\r\n\r\n public async onStop(_ctx: OrchestratorContext): Promise<void> {\r\n for (const s of this.subs) s.unsubscribe();\r\n this.subs = [];\r\n await this.flush();\r\n }\r\n\r\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\r\n return Promise.resolve();\r\n }\r\n\r\n private onLog(entry: LogEntry): void {\r\n this.push({ kind: \"log\", ...entry });\r\n }\r\n\r\n private onJob(evt: JobEvent): void {\r\n this.push({ kind: \"job\", ...evt });\r\n }\r\n\r\n private onNotify(msg: NotifyEvent): void {\r\n this.push({ ...msg,kind: \"ui\", });\r\n }\r\n\r\n private push(obj: object): void {\r\n this.buffer.push(JSON.stringify(obj));\r\n if (!this.timer) {\r\n this.timer = setTimeout(() => void this.flush(), 1000);\r\n }\r\n if (this.buffer.length > 200) void this.flush();\r\n }\r\n\r\n private async flush(): Promise<void> {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n if (this.buffer.length === 0) return;\r\n\r\n // await fs.mkdir(path.dirname(this.filePath), { recursive: true });\r\n // const lines = this.buffer.splice(0).join(\"\\n\") + \"\\n\";\r\n // await fs.appendFile(this.filePath, lines, \"utf8\");\r\n }\r\n}\r\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { NotifyScope } from \"../core/types.js\";\n\nexport class OSSignalOrchestrator implements Orchestrator {\n public readonly name = \"os-signals-orchestrator\";\n\n private sigint?: () => void;\n private sigterm?: () => void;\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n const handler = (sig: string) => {\n ctx.notifier.warn(`received ${sig}`, { scope: NotifyScope.System });\n ctx.engine.requestStop(sig);\n };\n\n // Store bound handlers so we can remove them later\n this.sigint = () => handler(\"SIGINT\");\n this.sigterm = () => handler(\"SIGTERM\");\n\n process.on(\"SIGINT\", this.sigint);\n process.on(\"SIGTERM\", this.sigterm);\n }\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\n return Promise.resolve();\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n if (this.sigint){\n process.off(\"SIGINT\", this.sigint);\n }\n if (this.sigterm){\n process.off(\"SIGTERM\", this.sigterm);\n }\n this.sigint = undefined;\n this.sigterm = undefined;\n\n ctx.notifier.info(\"OS signal handlers removed\", { scope: NotifyScope.System });\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n return Promise.resolve();\n }\n}\n", "import React from 'react';\nimport { render } from 'ink';\nimport { Engine } from '../core/engine.js';\nimport { EventBus } from '../core/eventBus.js';\nimport { EngineEventMap } from '../core/events.js';\nimport App from './app.js';\n\nexport function renderUi(engine: Engine, bus: EventBus<EngineEventMap>) {\n const { waitUntilExit } = render(React.createElement(App, { engine, bus }));\n return waitUntilExit();\n}\n", "import React, { useEffect, useCallback } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport { useStdoutDimensions } from './hooks/useStdoutDimensions.js';\nimport StatusBar from './components/StatusBar.js';\nimport LogPane from './components/LogPane.js';\nimport InputBar from './components/InputBar.js';\nimport ErrorBoundary from './components/ErrorBoundary.js';\nimport { EventBus } from '../core/eventBus.js';\nimport type { EngineEventMap } from '../core/events.js';\nimport { NotifyEvent } from '../core/events.js';\nimport { Engine } from '../core/engine.js';\nimport { NotifyKind, NotifyScope } from '../core/types.js';\nimport { AppContextProvider, useAppContext } from './context/AppContext.js';\n\ninterface AppProps {\n engine: Engine;\n bus: EventBus<EngineEventMap>;\n}\n\nfunction AppContent() {\n const { exit } = useApp();\n const { state, dispatch, engine, bus } = useAppContext();\n const [columns, rows] = useStdoutDimensions();\n const width = columns;\n const height = rows;\n\n // Create command handler\n const commandHandler = useCallback(\n (command: string) => bus.emit(\"console:command\", command),\n [bus]\n );\n\n // Calculate responsive layout\n // Reserve space for: StatusBar (1-2 lines), padding (2), InputBar (1), and some margin\n const availableHeight = Math.max(5, height - 5);\n const logPaneHeight = Math.min(availableHeight - 3, Math.max(5, Math.floor(availableHeight * 0.7)));\n\n // Handle Ctrl+C for graceful exit and arrow keys for history navigation\n useInput((input, key) => {\n if (key.ctrl && input === 'c') {\n engine.requestStop('user exit');\n return;\n }\n\n // Handle arrow keys for command history (only when not processing)\n if (!state.isProcessing && (key.upArrow || key.downArrow)) {\n if (state.commandHistory.length === 0) return;\n\n if (key.upArrow) {\n const newIndex = state.historyIndex === -1 ? state.commandHistory.length - 1 : Math.max(0, state.historyIndex - 1);\n dispatch({ type: 'SET_HISTORY_INDEX', payload: newIndex });\n dispatch({ type: 'SET_INPUT', payload: state.commandHistory[newIndex]! });\n } else if (key.downArrow) {\n if (state.historyIndex === -1) return;\n const newIndex = state.historyIndex + 1;\n if (newIndex >= state.commandHistory.length) {\n dispatch({ type: 'SET_HISTORY_INDEX', payload: -1 });\n dispatch({ type: 'SET_INPUT', payload: '' });\n } else {\n dispatch({ type: 'SET_HISTORY_INDEX', payload: newIndex });\n dispatch({ type: 'SET_INPUT', payload: state.commandHistory[newIndex]! });\n }\n }\n }\n });\n\n // Reset history index when user manually types - handled in reducer\n useEffect(() => {\n dispatch({ type: 'RESET_HISTORY_INDEX_IF_TYPING' });\n }, [state.input, dispatch]);\n\n const onSubmit = useCallback(\n async (line: string) => {\n const trimmed = line.trim();\n dispatch({ type: 'RESET_INPUT' });\n dispatch({ type: 'RESET_HISTORY_INDEX' });\n\n // Add to history if not empty and not duplicate of last command\n if (trimmed) {\n dispatch({ type: 'ADD_COMMAND_TO_HISTORY', payload: trimmed });\n }\n\n dispatch({ type: 'SET_IS_PROCESSING', payload: true });\n try {\n await commandHandler(trimmed);\n } catch (e: any) {\n const errorMessage = e?.message ?? String(e);\n const errorMsg = new NotifyEvent(`Command failed: ${errorMessage}`, { ts: Date.now(), kind: NotifyKind.Error });\n dispatch({ type: 'ADD_MESSAGE', payload: errorMsg });\n } finally {\n dispatch({ type: 'SET_IS_PROCESSING', payload: false });\n }\n },\n [dispatch, exit, commandHandler, engine]\n );\n\n const handleError = useCallback(\n (error: Error, errorInfo: React.ErrorInfo) => {\n const errorMsg = new NotifyEvent(`UI Error: ${error.message}`, { ts: Date.now(), kind: NotifyKind.Error });\n dispatch({ type: 'ADD_MESSAGE', payload: errorMsg });\n },\n [dispatch]\n );\n\n return (\n <ErrorBoundary onError={handleError}>\n <Box flexDirection=\"column\" padding={1} width={width}>\n <StatusBar width={width - 2} />\n <Box height={1} />\n <LogPane height={logPaneHeight} width={width - 2} />\n <Box height={1} />\n <InputBar width={width - 2} onSubmit={onSubmit} />\n </Box>\n </ErrorBoundary>\n );\n}\n\nexport default function App({ engine, bus }: AppProps) {\n return (\n <AppContextProvider engine={engine} bus={bus}>\n <AppContent />\n </AppContextProvider>\n );\n}\n", "import { useEffect, useState } from 'react';\n\n/**\n * Hook to get terminal dimensions (columns and rows)\n * Updates on terminal resize events\n */\nexport function useStdoutDimensions(): [number, number] {\n const [dimensions, setDimensions] = useState<[number, number]>(() => {\n // Get initial dimensions\n const columns = process.stdout.columns || 80;\n const rows = process.stdout.rows || 24;\n return [columns, rows];\n });\n\n useEffect(() => {\n // Update dimensions on resize\n const updateDimensions = () => {\n const columns = process.stdout.columns || 80;\n const rows = process.stdout.rows || 24;\n setDimensions([columns, rows]);\n };\n\n // Listen for resize events\n process.stdout.on('resize', updateDimensions);\n\n // Get initial dimensions\n updateDimensions();\n\n return () => {\n process.stdout.off('resize', updateDimensions);\n };\n }, []);\n\n return dimensions;\n}\n", "import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport { useAppContext } from '../context/AppContext.js';\n\n// Simplified state for now - will be enhanced when bridge integration is complete\ntype EngineState = 'IDLE' | 'RUNNING' | 'STOPPING' | 'STOPPED';\n\nfunction stateColor(s: EngineState): string {\n if (s === 'RUNNING') return 'green';\n if (s === 'STOPPING') return 'yellow';\n if (s === 'STOPPED') return 'red';\n return 'gray';\n}\n\nfunction connectionStatusColor(status: 'disconnected' | 'connecting' | 'connected'): string {\n if (status === 'connected') return 'green';\n if (status === 'connecting') return 'yellow';\n return 'red';\n}\n\nfunction connectionStatusText(status: 'disconnected' | 'connecting' | 'connected'): string {\n if (status === 'connected') return 'connected';\n if (status === 'connecting') return 'trying';\n return 'disconnected';\n}\n\nfunction truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return text.slice(0, Math.max(0, maxLength - 3)) + '...';\n}\n\nfunction StatusBar(props: { width: number }) {\n const { state } = useAppContext();\n const title = 'DeviceLink Agent';\n const debugEnabled = state.debugEnabled;\n const deviceId = state.deviceId ?? 'not signed in';\n const engineState = state.engineState;\n const stateColorValue = stateColor(engineState);\n const isProcessing = state.isProcessing;\n const connectionStatus = state.connectionStatus;\n const connectionRetryInSec = state.connectionRetryInSec;\n const refreshCountdownSec = state.refreshCountdownSec;\n\n // Real-time countdown for refresh\n const [currentRefreshCountdown, setCurrentRefreshCountdown] = useState<number | null>(refreshCountdownSec);\n const [currentRetryCountdown, setCurrentRetryCountdown] = useState<number | null>(connectionRetryInSec);\n\n // Sync with state changes\n useEffect(() => {\n setCurrentRefreshCountdown(refreshCountdownSec);\n }, [refreshCountdownSec]);\n\n useEffect(() => {\n setCurrentRetryCountdown(connectionRetryInSec);\n }, [connectionRetryInSec]);\n\n // Countdown timer for refresh\n useEffect(() => {\n if (refreshCountdownSec === null || refreshCountdownSec <= 0) {\n setCurrentRefreshCountdown(null);\n return;\n }\n \n setCurrentRefreshCountdown(refreshCountdownSec);\n \n const interval = setInterval(() => {\n setCurrentRefreshCountdown((prev) => {\n if (prev === null || prev <= 1) return null;\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [refreshCountdownSec]);\n\n // Countdown timer for retry\n useEffect(() => {\n if (connectionRetryInSec === null || connectionRetryInSec <= 0) {\n setCurrentRetryCountdown(null);\n return;\n }\n \n setCurrentRetryCountdown(connectionRetryInSec);\n \n const interval = setInterval(() => {\n setCurrentRetryCountdown((prev) => {\n if (prev === null || prev <= 1) return null;\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(interval);\n }, [connectionRetryInSec]);\n\n // Connection status\n const connStatusText = connectionStatusText(connectionStatus);\n const connStatusColor = connectionStatusColor(connectionStatus);\n\n // Calculate available width for right side\n const titleWidth = title.length;\n const minRightWidth = 30; // Minimum space needed\n const availableWidth = props.width - titleWidth - 2; // 2 for spacing\n\n // Build status display parts\n const statusElements: React.ReactNode[] = [];\n \n // Connection status\n statusElements.push(\n <Text key=\"conn\" color={connStatusColor}>{connStatusText}</Text>\n );\n \n // Retry countdown\n if (currentRetryCountdown !== null && currentRetryCountdown > 0) {\n statusElements.push(\n <Text key=\"retry\" color={connStatusColor}>retry in {currentRetryCountdown}s</Text>\n );\n }\n \n // Refresh countdown (only show when under 5 seconds)\n if (currentRefreshCountdown !== null && currentRefreshCountdown > 0 && currentRefreshCountdown <= 5) {\n statusElements.push(\n <Text key=\"refresh\" color=\"cyan\">refresh in {currentRefreshCountdown}s</Text>\n );\n }\n\n // If we have enough space, show horizontal layout\n if (availableWidth >= minRightWidth) {\n const deviceIdDisplay = truncate(deviceId, Math.max(5, availableWidth - 50));\n return (\n <Box justifyContent=\"space-between\" width={props.width}>\n <Box>\n <Text bold>{title}</Text>\n {debugEnabled && (\n <>\n <Text> </Text>\n <Text color=\"yellow\" bold>[DEBUG]</Text>\n </>\n )}\n </Box>\n <Box>\n {isProcessing && (\n <>\n <Text dimColor>\u23F3 </Text>\n </>\n )}\n <Text dimColor>device </Text>\n <Text>{deviceIdDisplay} </Text>\n <Text>\u00B7 </Text>\n <Text color={stateColorValue}>{engineState}</Text>\n {statusElements.length > 0 && (\n <>\n <Text> \u00B7 </Text>\n {statusElements.map((el, idx) => (\n <React.Fragment key={idx}>\n {idx > 0 && <Text> \u00B7 </Text>}\n {el}\n </React.Fragment>\n ))}\n </>\n )}\n </Box>\n </Box>\n );\n }\n\n // Otherwise, stack vertically\n const deviceIdDisplay = truncate(deviceId, props.width - 8);\n return (\n <Box flexDirection=\"column\" width={props.width}>\n <Box>\n <Text bold>{title}</Text>\n {debugEnabled && (\n <>\n <Text> </Text>\n <Text color=\"yellow\" bold>[DEBUG]</Text>\n </>\n )}\n </Box>\n <Box>\n {isProcessing && (\n <>\n <Text dimColor>\u23F3 </Text>\n </>\n )}\n <Text dimColor>device </Text>\n <Text>{deviceIdDisplay} </Text>\n <Text>\u00B7 </Text>\n <Text color={stateColorValue}>{engineState}</Text>\n {statusElements.length > 0 && (\n <>\n <Text> \u00B7 </Text>\n {statusElements.map((el, idx) => (\n <React.Fragment key={idx}>\n {idx > 0 && <Text> \u00B7 </Text>}\n {el}\n </React.Fragment>\n ))}\n </>\n )}\n </Box>\n </Box>\n );\n}\n\nexport default StatusBar;\nexport type { EngineState };\n", "import React, { createContext, useContext, useReducer, useMemo, useEffect, useState, ReactNode } from 'react';\nimport { EventBus } from '../../core/eventBus.js';\nimport { NotifyEvent } from '../../core/events.js';\nimport { Engine, EngineRuntime } from '../../core/engine.js';\nimport { EnginePhase, NotifyKind, NotifyScope } from '../../core/types.js';\nimport type { EngineState } from '../components/StatusBar.js';\nimport type { EngineEventMap } from '../../core/events.js';\n\n// State interface\ninterface AppState {\n input: string;\n messages: NotifyEvent[];\n engineState: EngineState;\n commandHistory: string[];\n historyIndex: number;\n isProcessing: boolean;\n debugEnabled: boolean;\n connectionStatus: 'disconnected' | 'connecting' | 'connected';\n connectionRetryInSec: number | null;\n refreshCountdownSec: number | null;\n deviceId: string | null;\n}\n\n// Action types\ntype AppAction =\n | { type: 'SET_INPUT'; payload: string }\n | { type: 'ADD_MESSAGE'; payload: NotifyEvent }\n | { type: 'SET_MESSAGES'; payload: NotifyEvent[] }\n | { type: 'SET_ENGINE_STATE'; payload: EngineState }\n | { type: 'ADD_COMMAND_TO_HISTORY'; payload: string }\n | { type: 'SET_HISTORY_INDEX'; payload: number }\n | { type: 'SET_IS_PROCESSING'; payload: boolean }\n | { type: 'SET_DEBUG_ENABLED'; payload: boolean }\n | { type: 'SET_CONNECTION_STATUS'; payload: 'disconnected' | 'connecting' | 'connected' }\n | { type: 'SET_CONNECTION_RETRY'; payload: number | null }\n | { type: 'SET_REFRESH_COUNTDOWN'; payload: number | null }\n | { type: 'SET_DEVICE_ID'; payload: string | null }\n | { type: 'RESET_INPUT' }\n | { type: 'RESET_HISTORY_INDEX' }\n | { type: 'RESET_HISTORY_INDEX_IF_TYPING' };\n\n// Context interface\ninterface AppContextValue {\n // State\n state: AppState;\n dispatch: React.Dispatch<AppAction>;\n \n // Readonly engine context\n readonly engine: Engine;\n readonly bus: EventBus<EngineEventMap>;\n readonly runtime: Readonly<EngineRuntime>;\n}\n\n// Create context\nconst AppContext = createContext<AppContextValue | null>(null);\n\nfunction messageUpsert(state: AppState, incoming: NotifyEvent): AppState {\n const messages = state.messages;\n\n // 1) Replace by id (rare in your setup, but keep it)\n const byId = messages.findIndex(m => m.id === incoming.id);\n if (byId !== -1) {\n const existing = messages[byId];\n const next = [...messages];\n // \u2705 preserve position/identity\n next[byId] = {\n ...incoming,\n id: existing.id,\n ts: existing.ts,\n } as NotifyEvent;\n return { ...state, messages: next };\n }\n\n // 2) Replace latest message in same group (your countdown case)\n if (incoming.groupKey) {\n for (let i = messages.length - 1; i >= 0; i--) {\n const existing = messages[i];\n if (existing.groupKey === incoming.groupKey) {\n const next = [...messages];\n // \u2705 preserve index + react key + sort position\n next[i] = {\n ...incoming,\n id: existing.id,\n ts: existing.ts,\n groupKey: existing.groupKey,\n } as NotifyEvent;\n return { ...state, messages: next };\n }\n }\n }\n\n // 3) Otherwise append\n return { ...state, messages: [...messages.slice(-380), incoming] };\n}\n\n\n// Reducer\nfunction appReducer(state: AppState, action: AppAction): AppState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, input: action.payload };\n \n case 'ADD_MESSAGE':\n return messageUpsert(state, action.payload);\n \n case 'SET_MESSAGES':\n return { ...state, messages: action.payload };\n \n case 'SET_ENGINE_STATE':\n return { ...state, engineState: action.payload };\n \n case 'ADD_COMMAND_TO_HISTORY':\n if (!action.payload) return state;\n const newHistory = state.commandHistory.length === 0 || state.commandHistory[state.commandHistory.length - 1] !== action.payload\n ? [...state.commandHistory, action.payload]\n : state.commandHistory;\n return { ...state, commandHistory: newHistory };\n \n case 'SET_HISTORY_INDEX':\n return { ...state, historyIndex: action.payload };\n \n case 'SET_IS_PROCESSING':\n return { ...state, isProcessing: action.payload };\n \n case 'SET_DEBUG_ENABLED':\n return { ...state, debugEnabled: action.payload };\n \n case 'SET_CONNECTION_STATUS':\n return { ...state, connectionStatus: action.payload };\n \n case 'SET_CONNECTION_RETRY':\n return { ...state, connectionRetryInSec: action.payload };\n \n case 'SET_REFRESH_COUNTDOWN':\n return { ...state, refreshCountdownSec: action.payload };\n \n case 'SET_DEVICE_ID':\n return { ...state, deviceId: action.payload };\n \n case 'RESET_INPUT':\n return { ...state, input: '' };\n \n case 'RESET_HISTORY_INDEX':\n return { ...state, historyIndex: -1 };\n \n case 'RESET_HISTORY_INDEX_IF_TYPING':\n // Reset history index if user is typing something different from current history item\n if (state.historyIndex !== -1) {\n const historyItem = state.commandHistory[state.historyIndex];\n if (historyItem !== undefined && state.input !== historyItem) {\n return { ...state, historyIndex: -1 };\n }\n }\n return state;\n \n default:\n return state;\n }\n}\n\n// Initial state\nconst initialState: AppState = {\n input: '',\n messages: [],\n engineState: 'IDLE',\n commandHistory: [],\n historyIndex: -1,\n isProcessing: false,\n debugEnabled: false,\n connectionStatus: 'disconnected',\n connectionRetryInSec: null,\n refreshCountdownSec: null,\n deviceId: null,\n};\n\n// Provider props\ninterface AppContextProviderProps {\n engine: Engine;\n bus: EventBus<EngineEventMap>;\n children: ReactNode;\n}\n\n// Provider component\nexport function AppContextProvider({ engine, bus, children }: AppContextProviderProps) {\n const [state, dispatch] = useReducer(appReducer, initialState);\n\n // Get readonly runtime reference - updates when engine runtime changes\n const [runtime, setRuntime] = useState<Readonly<EngineRuntime>>(() => {\n return Object.freeze({\n phase: engine.runtime.phase,\n flags: Object.freeze({\n debug: engine.runtime.flags.debug,\n }),\n }) as Readonly<EngineRuntime>;\n });\n\n useEffect(() => {\n bus.emit(\"ui:initialized\", Date.now());\n }, [bus]);\n\n // Single consolidated useEffect for all subscriptions and polling\n useEffect(() => {\n const phaseToState = (phase: string): EngineState => {\n if (phase === EnginePhase.Running) return 'RUNNING';\n if (phase === EnginePhase.Stopping) return 'STOPPING';\n if (phase === EnginePhase.Booting) return 'IDLE';\n return 'STOPPED';\n };\n\n const uiSub = bus.on('notify:event', (msg: NotifyEvent) => {\n dispatch({ type: 'ADD_MESSAGE', payload: msg });\n \n // Parse refresh countdown from auth refresh messages\n if (msg.groupKey?.startsWith('auth:refresh')) {\n if (msg.kind === NotifyKind.Info) {\n const match = msg.message.match(/refresh scheduled in (\\d+)s/);\n if (match) {\n const seconds = parseInt(match[1]!, 10);\n if (!isNaN(seconds)) {\n dispatch({ type: 'SET_REFRESH_COUNTDOWN', payload: seconds });\n }\n }\n } else if (msg.kind === NotifyKind.Success && msg.message.includes('refresh completed')) {\n // Clear countdown when refresh completes\n dispatch({ type: 'SET_REFRESH_COUNTDOWN', payload: null });\n }\n }\n });\n\n const updateRuntime = () => {\n const rt = engine.runtime;\n\n dispatch({ type: 'SET_ENGINE_STATE', payload: phaseToState(rt.phase) });\n dispatch({ type: 'SET_DEBUG_ENABLED', payload: rt.flags.debug });\n\n const deviceId = engine.configurationContext.configuration.device?.id ?? null;\n dispatch({ type: 'SET_DEVICE_ID', payload: deviceId });\n\n setRuntime(\n Object.freeze({\n phase: rt.phase,\n flags: Object.freeze({ debug: rt.flags.debug }),\n }) as Readonly<EngineRuntime>\n );\n };\n updateRuntime();\n\n // Listen for engine phase changes via events\n const startedSub = bus.on('engine:started', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'RUNNING' });\n updateRuntime();\n });\n\n const stoppingSub = bus.on('engine:stopping', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'STOPPING' });\n updateRuntime();\n });\n\n const stoppedSub = bus.on('engine:stopped', () => {\n dispatch({ type: 'SET_ENGINE_STATE', payload: 'STOPPED' });\n updateRuntime();\n });\n\n // Listen for WebSocket connection events\n const wsConnectingSub = bus.on('ws:connecting', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connecting' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsConnectedSub = bus.on('ws:connected', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connected' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsDisconnectedSub = bus.on('ws:disconnected', () => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'disconnected' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: null });\n });\n\n const wsRetryingSub = bus.on('ws:retrying', (payload: { retryInSec: number }) => {\n dispatch({ type: 'SET_CONNECTION_STATUS', payload: 'connecting' });\n dispatch({ type: 'SET_CONNECTION_RETRY', payload: payload.retryInSec });\n });\n\n const debugSub = bus.on(\"runtime:debug:changed\", ({ enabled }) => {\n dispatch({ type: \"SET_DEBUG_ENABLED\", payload: enabled });\n\n const rt = engine.runtime;\n setRuntime(\n Object.freeze({\n phase: rt.phase,\n flags: Object.freeze({ debug: enabled }),\n }) as Readonly<EngineRuntime>\n );\n });\n\n const configLoadedSub = bus.on(\"config:loaded\", (cfg) => {\n const deviceId = cfg.device?.id ?? null;\n dispatch({ type: \"SET_DEVICE_ID\", payload: deviceId });\n });\n\n // Initial welcome messages (only once)\n const welcomeMsg = new NotifyEvent('Welcome to DeviceLink Agent UI', { ts: Date.now(), kind: NotifyKind.Status });\n const helpMsg = new NotifyEvent('Type \"help\" for commands. Start bridge with: start or run', { ts: Date.now(), kind: NotifyKind.Status });\n dispatch({ type: 'SET_MESSAGES', payload: [welcomeMsg, helpMsg] });\n\n return () => {\n uiSub.unsubscribe();\n startedSub.unsubscribe();\n stoppingSub.unsubscribe();\n stoppedSub.unsubscribe();\n wsConnectingSub.unsubscribe();\n wsConnectedSub.unsubscribe();\n wsDisconnectedSub.unsubscribe();\n wsRetryingSub.unsubscribe();\n debugSub.unsubscribe();\n configLoadedSub.unsubscribe();\n };\n }, [bus, engine, dispatch]);\n\n // Context value\n const value = useMemo<AppContextValue>(\n () => ({\n state,\n dispatch,\n engine,\n bus,\n runtime,\n }),\n [state, engine, bus, runtime]\n );\n\n return <AppContext.Provider value={value}>{children}</AppContext.Provider>;\n}\n\n// Hook to use the context\nexport function useAppContext(): AppContextValue {\n const context = useContext(AppContext);\n if (!context) {\n throw new Error('useAppContext must be used within AppContextProvider');\n }\n return context;\n}\n\n// Custom hook for messages in different formats\nexport interface UseMessagesReturn {\n /** Raw, unfiltered messages */\n rawMessages: NotifyEvent[];\n \n /** Messages filtered for display (e.g., excludes refresh scheduled messages) */\n messagesToDisplay: NotifyEvent[];\n \n /** Get messages filtered by a custom predicate */\n getFilteredMessages: (predicate: (msg: NotifyEvent) => boolean) => NotifyEvent[];\n \n /** Get messages by kind */\n getMessagesByKind: (kind: NotifyKind) => NotifyEvent[];\n \n /** Get messages by scope */\n getMessagesByScope: (scope: NotifyScope) => NotifyEvent[];\n}\n\n/**\n * Custom hook that provides messages in different formats\n * \n * @example\n * ```tsx\n * // Basic usage - get filtered messages for display\n * const { messagesToDisplay } = useMessages();\n * \n * // Get raw unfiltered messages\n * const { rawMessages } = useMessages();\n * \n * // Custom filter\n * const { messagesToDisplay } = useMessages({\n * displayFilter: (msg) => msg.kind !== NotifyKind.Debug\n * });\n * \n * // Get messages by kind\n * const { getMessagesByKind } = useMessages();\n * const errors = getMessagesByKind(NotifyKind.Error);\n * ```\n * \n * @param options Configuration options for message filtering\n */\nexport function useMessages(options?: {\n /** Filter function to apply to messagesToDisplay (default: filters refresh scheduled messages) */\n displayFilter?: (msg: NotifyEvent) => boolean;\n}): UseMessagesReturn {\n const { state } = useAppContext();\n \n // Default filter: exclude auth refresh scheduled messages and token-refresh category (they're shown in status bar)\n const defaultDisplayFilter = (msg: NotifyEvent): boolean => {\n // Skip messages with token-refresh category\n if (msg.category?.includes('token-refresh')) {\n return false;\n }\n // Skip messages that match the refresh scheduled pattern\n if (msg.groupKey?.startsWith('auth:refresh') && msg.kind === NotifyKind.Info) {\n if (msg.message.includes('refresh scheduled in')) {\n return false;\n }\n }\n return true;\n };\n \n const displayFilter = options?.displayFilter ?? defaultDisplayFilter;\n \n // Memoize filtered messages\n const messagesToDisplay = useMemo(() => {\n return state.messages.filter(displayFilter);\n }, [state.messages, displayFilter]);\n \n // Helper functions\n const getFilteredMessages = useMemo(() => {\n return (predicate: (msg: NotifyEvent) => boolean) => {\n return state.messages.filter(predicate);\n };\n }, [state.messages]);\n \n const getMessagesByKind = useMemo(() => {\n return (kind: NotifyKind) => {\n return state.messages.filter(msg => msg.kind === kind);\n };\n }, [state.messages]);\n \n const getMessagesByScope = useMemo(() => {\n return (scope: NotifyScope) => {\n return state.messages.filter(msg => msg.scope === scope);\n };\n }, [state.messages]);\n \n return useMemo(() => ({\n rawMessages: state.messages,\n messagesToDisplay,\n getFilteredMessages,\n getMessagesByKind,\n getMessagesByScope,\n }), [state.messages, messagesToDisplay, getFilteredMessages, getMessagesByKind, getMessagesByScope]);\n}\n", "import React, { useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport { useMessages } from '../context/AppContext.js';\nimport { NotifyKind } from '../../core/types.js';\nimport { NotifyEvent } from '../../core/events.js';\n\nfunction kindColor(k: NotifyKind): string {\n if (k === NotifyKind.Error) return 'red';\n if (k === NotifyKind.Warning) return 'yellow';\n if (k === NotifyKind.Success) return 'green';\n if (k === NotifyKind.Info) return 'cyan';\n return 'white';\n}\n\nfunction kindTag(k: NotifyKind): string {\n if (k === NotifyKind.Error) return 'ERROR';\n if (k === NotifyKind.Warning) return 'WARN';\n if (k === NotifyKind.Success) return 'SUCCESS';\n if (k === NotifyKind.Info) return 'INFO';\n if (k === NotifyKind.Status) return 'STATUS';\n return 'INFO';\n}\n\nfunction formatTime(ts: number): string {\n const d = new Date(ts);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n}\n\nfunction wrapText(text: string, maxWidth: number): string[] {\n if (typeof text !== 'string') {\n text = String(text ?? '');\n }\n if (text.length <= maxWidth) return [text];\n const lines: string[] = [];\n let currentLine = '';\n const words = text.split(/(\\s+)/);\n for (const word of words) {\n if ((currentLine + word).length <= maxWidth) {\n currentLine += word;\n } else {\n if (currentLine) lines.push(currentLine);\n currentLine = '';\n let remainingWord = word;\n while (remainingWord.length > maxWidth) {\n lines.push(remainingWord.slice(0, maxWidth));\n remainingWord = remainingWord.slice(maxWidth);\n }\n currentLine = remainingWord;\n }\n }\n if (currentLine) lines.push(currentLine);\n return lines.length > 0 ? lines : [text];\n}\n\nconst LogPane = React.memo(\n function LogPane(props: { height?: number; width: number }) {\n const { messagesToDisplay } = useMessages();\n const h = props.height ?? 14;\n\n const timestampWidth = 9; // \"HH:MM:SS \"\n const kindTagWidth = 8; // \"INFO \" or \"ERROR \"\n const padding = 2;\n const border = 2;\n const availableWidth = Math.max(\n 20,\n props.width - timestampWidth - kindTagWidth - padding - border,\n );\n\n const view = useMemo(() => {\n return messagesToDisplay.slice(-h);\n }, [messagesToDisplay, h]);\n\n const wrappedMessages = useMemo(() => {\n return view.flatMap((msg) => {\n const timeStr = formatTime(msg.ts);\n const kindStr = kindTag(msg.kind);\n const wrapped = wrapText(msg.message, availableWidth);\n return wrapped.map((line, lineIndex) => ({\n msg,\n lineIndex,\n time: lineIndex === 0 ? timeStr : '',\n kind: lineIndex === 0 ? kindStr : '',\n message: line,\n isContinuation: lineIndex > 0,\n }));\n });\n }, [view, availableWidth]);\n\n const displayMessages = wrappedMessages.slice(-h);\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n height={h + 2}\n width={props.width}\n >\n {displayMessages.length === 0 ? (\n <Text dimColor>(no messages)</Text>\n ) : (\n displayMessages.map((item) => (\n <LogRow key={`${item.msg.id}:${item.lineIndex}`} item={item} />\n ))\n )}\n </Box>\n );\n },\n (prevProps, nextProps) => prevProps.height === nextProps.height && prevProps.width === nextProps.width,\n);\n\nconst LogRow = React.memo(function LogRow({\n item,\n}: {\n item: {\n time: string;\n kind: string;\n message: string;\n isContinuation: boolean;\n msg: NotifyEvent;\n lineIndex: number;\n };\n}) {\n return (\n <Text>\n {item.time && <Text dimColor>{item.time} </Text>}\n {item.kind && <Text color={kindColor(item.msg.kind)}>{item.kind}</Text>}\n {item.kind && <Text> </Text>}\n {item.isContinuation && <Text dimColor> </Text>}\n <Text>{item.message}</Text>\n </Text>\n );\n});\n\nexport default LogPane;\n", "import React from 'react';\nimport { Box, Text, useFocus } from 'ink';\nimport TextInput from 'ink-text-input';\nimport { useAppContext } from '../context/AppContext.js';\n\nconst InputBar = React.memo(function InputBar(props: {\n onSubmit: (v: string) => void;\n width: number;\n isPassphraseMode?: boolean;\n passphraseError?: string;\n}) {\n const { state, dispatch } = useAppContext();\n const { isFocused } = useFocus({ autoFocus: true, isActive: !state.isProcessing });\n\n\n const prompt = props.isPassphraseMode ? 'passphrase> ' : 'dlink> ';\n const maxInputWidth = Math.max(10, props.width - prompt.length - 2);\n\n return (\n <Box flexDirection=\"column\" width={props.width}>\n <Box width={props.width}>\n <Text color={props.isPassphraseMode ? 'cyan' : 'green'}>{prompt}</Text>\n <Box width={maxInputWidth}>\n {state.isProcessing ? (\n <Text dimColor italic>\n Processing...\n </Text>\n ) : (\n <TextInput\n key={`input-${state.historyIndex}-${props.isPassphraseMode ? 'passphrase' : 'normal'}`}\n value={state.input}\n onChange={(value) => dispatch({ type: 'SET_INPUT', payload: value })}\n onSubmit={props.onSubmit}\n placeholder={isFocused ? undefined : props.isPassphraseMode ? 'Enter passphrase...' : 'Type a command or \"help\"'}\n mask={props.isPassphraseMode ? '*' : undefined}\n />\n )}\n </Box>\n </Box>\n {props.passphraseError && (\n <Box marginTop={1}>\n <Text color=\"red\">{props.passphraseError}</Text>\n </Box>\n )}\n </Box>\n );\n});\n\nexport default InputBar;\n", "import React, { Component, type ReactNode } from 'react';\nimport { Box, Text } from 'ink';\n\ninterface Props {\n children: ReactNode;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n}\n\ninterface State {\n hasError: boolean;\n error: Error | null;\n}\n\nexport default class ErrorBoundary extends Component<Props, State> {\n constructor(props: Props) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): State {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n if (this.props.onError) {\n this.props.onError(error, errorInfo);\n }\n }\n\n render() {\n if (this.state.hasError && this.state.error) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box borderStyle=\"round\" borderColor=\"red\" paddingX={1}>\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n \u26A0\uFE0F Application Error\n </Text>\n <Box height={1} />\n <Text color=\"red\">{this.state.error.message}</Text>\n {this.state.error.stack && (\n <>\n <Box height={1} />\n <Text dimColor>{this.state.error.stack}</Text>\n </>\n )}\n <Box height={1} />\n <Text dimColor>Press Ctrl+C to exit</Text>\n </Box>\n </Box>\n </Box>\n );\n }\n\n return this.props.children;\n }\n}\n", "/**\n * Command parser with callback registry\n * Parses argv to extract commands and routes them to registered handlers\n */\n\nexport interface ParsedCommand {\n command: string;\n subcommand?: string;\n args: string[];\n options: Record<string, string | boolean>;\n}\n\nexport type CommandHandler = (parsed: ParsedCommand) => Promise<void> | void;\n\nexport class CommandParser {\n private readonly handlers: Map<string, CommandHandler> = new Map();\n private readonly subcommandHandlers: Map<string, Map<string, CommandHandler>> = new Map();\n\n /**\n * Register a command handler\n * @param command - Command name (e.g., 'signin', 'status')\n * @param handler - Callback function to execute\n */\n public command(command: string, handler: CommandHandler): this {\n if (this.handlers.has(command)) {\n throw new Error(`Command '${command}' is already registered`);\n }\n this.handlers.set(command, handler);\n return this;\n }\n\n /**\n * Register a subcommand handler\n * @param command - Parent command name (e.g., 'roots')\n * @param subcommand - Subcommand name (e.g., 'add', 'list')\n * @param handler - Callback function to execute\n */\n public subcommand(command: string, subcommand: string, handler: CommandHandler): this {\n if (!this.subcommandHandlers.has(command)) {\n this.subcommandHandlers.set(command, new Map());\n }\n const subcommands = this.subcommandHandlers.get(command)!;\n if (subcommands.has(subcommand)) {\n throw new Error(`Subcommand '${command} ${subcommand}' is already registered`);\n }\n subcommands.set(subcommand, handler);\n return this;\n }\n\n /**\n * Convert a command string to argv array format\n * @param command - Command string to tokenize\n * @returns argv array in process.argv format\n */\n private commandStringToArgv(command: string): string[] {\n // Simulate process.argv format: ['node', 'script', ...args]\n // The parser expects to skip the first two, so we add dummy entries\n const tokens: string[] = [];\n let current = '';\n let inQuotes = false;\n let quoteChar = '';\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i]!;\n \n if (char === '\"' || char === \"'\") {\n if (inQuotes && char === quoteChar) {\n // Closing quote - push current token (even if empty for \"\")\n tokens.push(current);\n current = '';\n inQuotes = false;\n quoteChar = '';\n } else if (!inQuotes) {\n // Opening quote - save any current token first\n if (current) {\n tokens.push(current);\n current = '';\n }\n inQuotes = true;\n quoteChar = char;\n } else {\n // Different quote type inside quotes - treat as literal\n current += char;\n }\n } else if (char === ' ' && !inQuotes) {\n if (current) {\n tokens.push(current);\n current = '';\n }\n // Skip spaces outside quotes\n } else {\n current += char;\n }\n }\n \n // Push remaining token (or empty string if we ended in quotes)\n if (inQuotes || current) {\n tokens.push(current);\n }\n \n return ['node', 'script', ...tokens];\n }\n\n /**\n * Parse a command string and extract command information\n * @param commandString - Command string to parse\n * @returns Parsed command or null if no command found\n */\n public parseString(commandString: string): ParsedCommand | null {\n const argv = this.commandStringToArgv(commandString);\n return this.parse(argv);\n }\n\n /**\n * Parse argv and extract command information\n * @param argv - Process argv array\n * @returns Parsed command or null if no command found\n */\n public parse(argv: string[]): ParsedCommand | null {\n // Skip first two args (node executable and script path)\n const args = argv.slice(2);\n if (args.length === 0) {\n return null;\n }\n\n const result: ParsedCommand = {\n command: '',\n args: [],\n options: {},\n };\n\n let i = 0;\n \n // Extract command name (first non-flag argument)\n while (i < args.length && args[i]?.startsWith('--')) {\n i++;\n }\n \n if (i >= args.length || !args[i]) {\n return null;\n }\n\n result.command = args[i]!;\n i++;\n\n // Check for subcommand (next non-flag argument)\n while (i < args.length && args[i]?.startsWith('--')) {\n i++;\n }\n\n if (i < args.length && args[i] && !args[i]!.startsWith('--')) {\n result.subcommand = args[i]!;\n i++;\n }\n\n // Parse remaining arguments and options\n while (i < args.length) {\n const arg = args[i]!;\n \n if (arg.startsWith('--')) {\n // Option flag\n const optionName = arg.slice(2);\n \n // Check for --flag=value format\n if (optionName.includes('=')) {\n const [key, value] = optionName.split('=', 2);\n result.options[key] = value || true;\n } else {\n // Check if next arg is a value (not a flag)\n const nextArg = args[i + 1];\n if (nextArg && !nextArg.startsWith('--')) {\n result.options[optionName] = nextArg;\n i++; // Skip the value\n } else {\n // Boolean flag\n result.options[optionName] = true;\n }\n }\n } else {\n // Positional argument\n result.args.push(arg);\n }\n \n i++;\n }\n\n return result;\n }\n\n /**\n * Parse and execute command from argv\n * @param argv - Process argv array\n * @returns true if a command was found and executed, false otherwise\n */\n public async execute(argv: string[]): Promise<boolean> {\n const parsed = this.parse(argv);\n if (!parsed) {\n return false;\n }\n\n // Try subcommand first\n if (parsed.subcommand) {\n const subcommands = this.subcommandHandlers.get(parsed.command);\n if (subcommands) {\n const handler = subcommands.get(parsed.subcommand);\n if (handler) {\n await handler(parsed);\n return true;\n }\n }\n }\n\n // Try main command\n const handler = this.handlers.get(parsed.command);\n if (handler) {\n await handler(parsed);\n return true;\n }\n\n return false;\n }\n\n /**\n * Check if a command exists in the registry\n */\n public hasCommand(command: string, subcommand?: string): boolean {\n if (subcommand) {\n const subcommands = this.subcommandHandlers.get(command);\n return subcommands?.has(subcommand) ?? false;\n }\n return this.handlers.has(command);\n }\n\n /**\n * Get all registered command names\n */\n public getCommands(): string[] {\n return Array.from(this.handlers.keys());\n }\n}\n", "import { ParsedCommand } from \"./command.parser\";\nimport { JobType } from \"../core/job\";\n\nexport enum ConsoleCommandKind {\n Start = \"start\",\n Stop = \"stop\",\n SignIn = \"signin\",\n SignOut = \"signout\",\n Status = \"status\",\n RootsAdd = \"roots-add\",\n RootsList = \"roots-list\",\n Run = \"run\",\n Doctor = \"doctor\",\n DebugOn = \"debug-on\",\n DebugOff = \"debug-off\",\n Replace = \"replace\",\n }\n\nexport class ConsoleCommandInput {\n public readonly kind: ConsoleCommandKind;\n public readonly payloadJson: string | null;\n \n public constructor(kind: ConsoleCommandKind, payloadJson: string | null) {\n this.kind = kind;\n this.payloadJson = payloadJson;\n }\n }\n\n \n/**\n * Result of a pattern match\n */\nexport interface CommandMatchResult {\n handled: boolean;\n kind?: ConsoleCommandKind;\n job?: ConsoleCommandInput;\n }\n\n/**\n * Pattern matcher function type\n */\nexport type CommandMatcher = (params: string[], parsed: ParsedCommand) => CommandMatchResult;\n\n/**\n * Dispatchable job containing handler and input\n */\nexport interface DispatchableJob<TIn> {\n handler: JobType<TIn, unknown>;\n input: TIn;\n}\n\n/**\n * Command job builder using pattern matching\n */\nexport class CommandJobBuilder {\n private readonly matchers: CommandMatcher[] = [];\n /**\n * Register a pattern matcher function\n * @param matcher - Function that takes command params and parsed command, returns match result\n * @returns this for chaining\n */\n public register(matcher: CommandMatcher): this {\n this.matchers.push(matcher);\n return this;\n }\n \n /**\n * Build a dispatchable job from a parsed command\n * @param parsed - The parsed command\n * @returns DispatchableJob or null if no match found\n */\n public build(parsed: ParsedCommand): ConsoleCommandInput | null {\n // Build params array from command and subcommand\n const params: string[] = [parsed.command];\n if (parsed.subcommand) {\n params.push(parsed.subcommand);\n }\n \n // Try each matcher in order, stop at first match\n for (const matcher of this.matchers) {\n const result = matcher(params, parsed);\n if (result.handled) {\n // If job is provided, use it; otherwise create from kind\n let input: ConsoleCommandInput;\n if (result.job) {\n input = result.job;\n } else if (result.kind) {\n input = this.createCommandInput(result.kind, parsed);\n } else {\n // If handled but no job/kind, return null (handled but invalid)\n return null;\n }\n \n return input;\n }\n }\n \n return null;\n }\n \n /**\n * Create a ConsoleCommandInput from kind and parsed command\n */\n private createCommandInput(kind: ConsoleCommandKind, parsed: ParsedCommand): ConsoleCommandInput {\n const payload = {\n command: parsed.command,\n subcommand: parsed.subcommand,\n args: parsed.args,\n options: parsed.options,\n };\n return new ConsoleCommandInput(kind, JSON.stringify(payload));\n }\n }\n \n ", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { NotifyScope, DispatchStatus, NotifyKind } from \"../core/types.js\";\nimport { renderUi } from \"../ui/index.js\";\nimport { CommandParser } from \"../utils/command.parser.js\";\nimport { ConsoleCommandKind, CommandJobBuilder } from \"../utils/command-job.builder.js\";\nimport { consoleCommandCall } from \"../jobs/consoleCommand.js\";\n\n\nexport class ConsoleCommandOutput {\n public readonly ok: boolean;\n public constructor(ok: boolean) {\n this.ok = ok;\n }\n}\n\nexport class ConsoleOrchestrator implements Orchestrator {\n public readonly name = \"console-orchestrator\";\n public readonly commandParser: CommandParser;\n public readonly commandJobBuilder: CommandJobBuilder;\n\n public constructor() {\n this.commandParser = new CommandParser();\n this.commandJobBuilder = new CommandJobBuilder();\n \n // Register all command mappings\n this.setupCommandMappings();\n }\n public onRegister(_ctx: OrchestratorContext): void {\n // Nothing to do on register\n }\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"Starting console orchestrator (UI)\", { scope: NotifyScope.System });\n \n ctx.on(\"console:command\", async (event) => {\n try {\n // Parse the command string\n const parsed = this.commandParser.parseString(event);\n \n if (!parsed) {\n ctx.notifier.warn(\"Invalid command format\");\n return;\n }\n \n // Build the command job\n const input = this.commandJobBuilder.build(parsed);\n \n if (!input) {\n ctx.notifier.warn(`Unknown command: ${parsed.command}${parsed.subcommand ? ' ' + parsed.subcommand : ''}`);\n return;\n }\n\n switch (input.kind) {\n case ConsoleCommandKind.SignIn:\n ctx.bus.emit(\"auth:signin:requested\", void 0);\n ctx.notifier.info(\"Sign-in requested\");\n break;\n\n case ConsoleCommandKind.SignOut:\n ctx.bus.emit(\"auth:signout:requested\", void 0);\n ctx.notifier.info(\"Sign-out requested\");\n break;\n\n case ConsoleCommandKind.DebugOn:\n ctx.flags.debug = true;\n ctx.bus.emit(\"runtime:debug:changed\", { enabled: true });\n ctx.notifier.success(\"Debug mode enabled\");\n break;\n\n case ConsoleCommandKind.DebugOff:\n ctx.flags.debug = false;\n ctx.bus.emit(\"runtime:debug:changed\", { enabled: false });\n ctx.notifier.success(\"Debug mode disabled\");\n break;\n\n case ConsoleCommandKind.Replace:\n ctx.bus.emit(\"auth:session_conflict:resolve\", { choice: 'USE_NEW' });\n break;\n\n default:\n ctx.notifier.warn(`Command not implemented: ${input.kind}`);\n break;\n }\n\n // // Dispatch the command\n // const call = consoleCommandCall(input);\n // const result = await ctx.engine.dispatch(call);\n // if (result.status !== DispatchStatus.Success) {\n // throw new Error(`Command '${input.kind}' failed: ${result.error ?? 'Unknown error'}`);\n // }\n \n // // Emit success message\n // ctx.notifier.success(`Command '${parsed.command}${parsed.subcommand ? ' ' + parsed.subcommand : ''}' executed`);\n } catch (error: any) {\n const errorMessage = error?.message ?? String(error);\n ctx.notifier.error(`Command failed: ${errorMessage}`);\n ctx.notifier.error(`Command execution error: ${errorMessage}`);\n }\n });\n\n }\n\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"Console orchestrator started\", { scope: NotifyScope.System });\n renderUi(ctx.engine, ctx.bus);\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n ctx.notifier.info(\"UI exited, stopping engine\", { scope: NotifyScope.System });\n if (ctx.engine) {\n ctx.engine.requestStop('UI exited');\n }\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n // Nothing to do\n }\n\n \n\n /**\n * Setup all command mappings using pattern matching\n */\n private setupCommandMappings(): void {\n const builder = this.commandJobBuilder;\n\n // Single command patterns\n builder.register((params) => {\n if (params.length === 1) {\n const cmd = params[0];\n if (cmd === 'start' || cmd === 'run') {\n return { handled: true, kind: ConsoleCommandKind.Start };\n }\n if (cmd === 'stop') {\n return { handled: true, kind: ConsoleCommandKind.Stop };\n }\n if (cmd === 'signin') {\n return { handled: true, kind: ConsoleCommandKind.SignIn };\n }\n if (cmd === 'signout') {\n return { handled: true, kind: ConsoleCommandKind.SignOut };\n }\n if (cmd === 'status') {\n return { handled: true, kind: ConsoleCommandKind.Status };\n }\n if (cmd === 'doctor') {\n return { handled: true, kind: ConsoleCommandKind.Doctor };\n }\n if (cmd === 'replace' || cmd === 'yes' || cmd === 'y') {\n return { handled: true, kind: ConsoleCommandKind.Replace };\n }\n }\n return { handled: false };\n });\n\n // Subcommand patterns\n builder.register((params) => {\n if (params.length === 2) {\n const [cmd, subcmd] = params;\n if (cmd === 'roots') {\n if (subcmd === 'add') {\n return { handled: true, kind: ConsoleCommandKind.RootsAdd };\n }\n if (subcmd === 'list') {\n return { handled: true, kind: ConsoleCommandKind.RootsList };\n }\n }\n if (cmd === 'debug') {\n if (subcmd === 'on') {\n return { handled: true, kind: ConsoleCommandKind.DebugOn };\n }\n if (subcmd === 'off') {\n return { handled: true, kind: ConsoleCommandKind.DebugOff };\n }\n }\n }\n return { handled: false };\n });\n\n // Handle debug on/off as args (backward compatibility)\n builder.register((params, parsed) => {\n if (params.length === 1 && params[0] === 'debug' && parsed.args.length > 0) {\n const arg = parsed.args[0];\n if (arg === 'on') {\n return { handled: true, kind: ConsoleCommandKind.DebugOn };\n }\n if (arg === 'off') {\n return { handled: true, kind: ConsoleCommandKind.DebugOff };\n }\n }\n return { handled: false };\n });\n }\n\n}\n", "import WebSocket from \"ws\";\nimport * as Common from \"@devicelink-workspace/common\";\n\nexport type SocketState =\n | { kind: \"DISCONNECTED\" }\n | { kind: \"CONNECTING\" }\n | { kind: \"CONNECTED\" }\n | { kind: \"RETRYING\"; retryInSec: number }; // kept for compatibility (not used internally)\n\ntype SendItem = {\n data: WebSocket.Data;\n cb?: (err?: Error) => void;\n expiresAt: number;\n};\n\nexport class RecoverableSocket {\n private ws: WebSocket | null = null;\n private state: SocketState = { kind: \"DISCONNECTED\" };\n\n private stopped = false;\n private connecting = false;\n\n /** Increases each connection attempt; used to ignore events from old sockets */\n private connId = 0;\n\n /** Connection timeout */\n private connectionTimeout: NodeJS.Timeout | null = null;\n\n /** Heartbeat */\n private heartbeatInterval: NodeJS.Timeout | null = null;\n private heartbeatTimeout: NodeJS.Timeout | null = null;\n private awaitingPong = false;\n\n /** Send queue */\n private sendQueue: SendItem[] = [];\n\n private readonly url: string;\n private readonly abortSignal?: AbortSignal;\n\n private readonly connectionTimeoutMs: number;\n private readonly heartbeatIntervalMs: number;\n private readonly pongTimeoutMs: number;\n\n private readonly maxSendQueueSize: number;\n private readonly sendQueueItemTtlMs: number;\n\n // Single callbacks\n private onStateChangeCallback?: (state: SocketState) => void;\n private onErrorCallback?: (error: Error) => void;\n private onConnectedCallback?: (ws: WebSocket) => void;\n private onDisconnectedCallback?: (code: number, reason: string) => void;\n private onMessageCallback?: (data: WebSocket.Data) => void;\n\n constructor(\n url: string,\n options: {\n abortSignal?: AbortSignal;\n /** How long to wait for TCP/TLS+WS handshake */\n connectionTimeoutMs?: number; // default 10s\n /** Heartbeat ping interval */\n heartbeatIntervalMs?: number; // default 20s\n /** How long to wait for a pong after ping */\n pongTimeoutMs?: number; // default 10s\n /** Queue outgoing sends while disconnected */\n maxSendQueueSize?: number; // default 1000\n sendQueueItemTtlMs?: number; // default 60s\n } = {}\n ) {\n this.url = url;\n this.abortSignal = options.abortSignal;\n\n this.connectionTimeoutMs = options.connectionTimeoutMs ?? 10_000;\n this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? 20_000;\n this.pongTimeoutMs = options.pongTimeoutMs ?? 10_000;\n\n this.maxSendQueueSize = options.maxSendQueueSize ?? 1000;\n this.sendQueueItemTtlMs = options.sendQueueItemTtlMs ?? 60_000;\n\n if (this.abortSignal) {\n this.abortSignal.addEventListener(\n \"abort\",\n () => {\n this.stop();\n },\n { once: true }\n );\n }\n }\n\n // --- Public API ------------------------------------------------------------\n\n public registerOnStateChangeCallback(handler: (state: SocketState) => void): void {\n this.onStateChangeCallback = handler;\n }\n public registerOnErrorCallback(handler: (error: Error) => void): void {\n this.onErrorCallback = handler;\n }\n public registerOnConnectedCallback(handler: (ws: WebSocket) => void): void {\n this.onConnectedCallback = handler;\n }\n public registerOnDisconnectedCallback(handler: (code: number, reason: string) => void): void {\n this.onDisconnectedCallback = handler;\n }\n public registerOnMessageCallback(handler: (data: WebSocket.Data) => void): void {\n this.onMessageCallback = handler;\n }\n\n public getState(): SocketState {\n return this.state;\n }\n\n public getSocket(): WebSocket | null {\n return this.ws;\n }\n\n public isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Single connection attempt (NO internal retry). */\n public async connect(): Promise<void> {\n if (this.stopped) throw new Error(\"Socket is stopped\");\n if (this.connecting || this.isConnected()) return;\n\n this.connecting = true;\n this.updateState({ kind: \"CONNECTING\" });\n\n try {\n await this.connectWebSocketOnce();\n } catch (e: any) {\n const err = e instanceof Error ? e : new Error(String(e));\n this.onErrorCallback?.(err);\n this.updateState({ kind: \"DISCONNECTED\" });\n throw err;\n } finally {\n this.connecting = false;\n }\n }\n\n /** Permanently stop + disconnect. */\n public stop(): void {\n this.stopped = true;\n this.disconnect(true);\n }\n\n /** Disconnect current socket (graceful close, then terminate fallback). */\n public disconnect(permanent = false): void {\n if (permanent) this.stopped = true;\n\n // Cancel connect timeout\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = null;\n }\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n const ws = this.ws;\n this.ws = null;\n this.connecting = false;\n\n if (ws) {\n // IMPORTANT: close handshake first so server sees a real code (not 1005)\n this.closeGracefullyThenTerminate(ws, 1000, \"client disconnect\", 2000);\n }\n\n this.updateState({ kind: \"DISCONNECTED\" });\n }\n\n /**\n * Send data.\n * - If connected: sends immediately.\n * - If disconnected: queues until reconnected (up to limits).\n */\n public send(data: WebSocket.Data, cb?: (err?: Error) => void): void {\n if (this.stopped) {\n cb?.(new Error(\"Socket is stopped\"));\n return;\n }\n\n const ws = this.ws;\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(data, (err) => cb?.(err ?? undefined));\n return;\n }\n\n // Queue while offline\n const now = Date.now();\n this.pruneSendQueue(now);\n\n if (this.sendQueue.length >= this.maxSendQueueSize) {\n cb?.(new Error(`Send queue full (max ${this.maxSendQueueSize})`));\n return;\n }\n\n this.sendQueue.push({\n data,\n cb,\n expiresAt: now + this.sendQueueItemTtlMs,\n });\n }\n\n // --- Internals ------------------------------------------------------------\n\n /**\n * The key fix for \"1005\": never hard-kill immediately when we can close properly.\n * We send a close frame, then if it doesn't close soon, we terminate as a fallback.\n */\n private closeGracefullyThenTerminate(\n ws: WebSocket,\n code: number,\n reason: string,\n timeoutMs: number\n ) {\n try {\n if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {\n ws.close(code, reason);\n }\n } catch {\n // ignore\n }\n\n const t = setTimeout(() => {\n try {\n ws.terminate();\n } catch {\n // ignore\n }\n }, timeoutMs);\n\n ws.once(\"close\", () => clearTimeout(t));\n }\n\n private async connectWebSocketOnce(): Promise<void> {\n const myConnId = ++this.connId;\n\n return new Promise((resolve, reject) => {\n if (this.stopped) {\n reject(new Error(\"Socket is stopped\"));\n return;\n }\n\n let opened = false;\n let settled = false;\n\n const cleanup = () => {\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = null;\n }\n };\n\n const settleResolve = () => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve();\n };\n\n const settleReject = (error: Error, ws?: WebSocket) => {\n if (settled) return;\n settled = true;\n cleanup();\n\n // If we created a socket, try close handshake first, terminate later.\n if (ws) {\n const code = opened ? 1011 : 1006; // 1006 isn't sent on wire; just local intent\n this.closeGracefullyThenTerminate(ws, 1000, \"connect failed\", 1500);\n }\n\n reject(error);\n };\n\n let ws: WebSocket;\n try {\n ws = new WebSocket(this.url);\n\n // Connection timeout\n this.connectionTimeout = setTimeout(() => {\n settleReject(\n new Error(\n `Connection timeout: unable to connect to ${this.url} within ${this.connectionTimeoutMs}ms`\n ),\n ws\n );\n }, this.connectionTimeoutMs);\n\n ws.on(\"open\", () => {\n opened = true;\n\n if (myConnId !== this.connId) {\n // Old attempt opened late \u2014 close it gracefully\n this.closeGracefullyThenTerminate(ws, 1000, \"stale connection\", 500);\n return;\n }\n\n this.ws = ws;\n this.retryResetOnConnect();\n\n this.updateState({ kind: \"CONNECTED\" });\n this.onConnectedCallback?.(ws);\n\n // Heartbeat & queue flush\n this.startHeartbeat(myConnId);\n this.flushSendQueue();\n\n settleResolve();\n });\n\n ws.on(\"error\", (error) => {\n if (myConnId !== this.connId) return;\n\n const err = error instanceof Error ? error : new Error(String(error));\n\n // If not connected yet, fail the attempt\n if (!opened && !settled) {\n settleReject(err, ws);\n return;\n }\n\n // If already open, surface error; close will follow in many cases\n this.onErrorCallback?.(err);\n });\n\n ws.on(\"close\", (code, reason) => {\n if (myConnId !== this.connId) return;\n\n const reasonStr = reason?.toString?.() || \"\";\n\n // If close happens before open & before settleResolve, treat as connect failure\n if (!opened && !settled) {\n this.ws = null;\n this.stopHeartbeat();\n this.updateState({ kind: \"DISCONNECTED\" });\n settleReject(new Error(`WebSocket closed before connection established: ${code} ${reasonStr}`), ws);\n return;\n }\n\n // Normal disconnect after being connected\n if (this.ws === ws) this.ws = null;\n\n this.stopHeartbeat();\n this.updateState({ kind: \"DISCONNECTED\" });\n this.onDisconnectedCallback?.(code, reasonStr || `code ${code}`);\n });\n\n ws.on(\"message\", (data) => {\n if (myConnId !== this.connId) {\n this.onErrorCallback?.(new Error('Message ignored - connection ID mismatch'));\n return;\n }\n if (this.ws !== ws) {\n this.onErrorCallback?.(new Error('Message ignored - socket mismatch'));\n return;\n }\n this.onMessageCallback?.(data);\n });\n\n // Heartbeat pong handler\n ws.on(\"pong\", () => {\n if (myConnId !== this.connId) return;\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n });\n\n // Abort signal\n if (this.abortSignal) {\n this.abortSignal.addEventListener(\n \"abort\",\n () => {\n if (myConnId !== this.connId) return;\n\n // Close handshake first; terminate later if needed\n this.closeGracefullyThenTerminate(ws, 1000, \"aborted\", 1000);\n\n if (!settled) {\n settleReject(new Error(\"Connection aborted\"), ws);\n }\n },\n { once: true }\n );\n }\n } catch (e: any) {\n const err = e instanceof Error ? e : new Error(String(e));\n reject(err);\n }\n });\n }\n\n private retryResetOnConnect() {\n // kept as a hook in case you later want it; no internal retry now\n }\n\n private startHeartbeat(myConnId: number): void {\n this.stopHeartbeat();\n\n const ws = this.ws;\n if (!ws) return;\n\n this.awaitingPong = false;\n\n this.heartbeatInterval = setInterval(() => {\n if (this.stopped) return;\n if (myConnId !== this.connId) return;\n\n const current = this.ws;\n if (!current || current.readyState !== WebSocket.OPEN) return;\n\n // If previous ping wasn't answered -> close handshake then terminate\n if (this.awaitingPong) {\n this.closeGracefullyThenTerminate(current, 4000, \"pong timeout\", 1000);\n return;\n }\n\n this.awaitingPong = true;\n\n try {\n current.ping();\n } catch {\n this.closeGracefullyThenTerminate(current, 1011, \"ping failed\", 1000);\n return;\n }\n\n if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = setTimeout(() => {\n if (myConnId !== this.connId) return;\n const cur = this.ws;\n if (!cur) return;\n this.closeGracefullyThenTerminate(cur, 4000, \"pong timeout\", 1000);\n }, this.pongTimeoutMs);\n }, this.heartbeatIntervalMs);\n }\n\n private stopHeartbeat(): void {\n this.awaitingPong = false;\n\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n }\n\n private flushSendQueue(): void {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n\n const now = Date.now();\n this.pruneSendQueue(now);\n\n const items = this.sendQueue;\n this.sendQueue = [];\n\n for (const item of items) {\n ws.send(item.data, (err) => item.cb?.(err ?? undefined));\n }\n }\n\n private pruneSendQueue(now: number): void {\n if (this.sendQueue.length === 0) return;\n\n const kept: SendItem[] = [];\n for (const item of this.sendQueue) {\n if (item.expiresAt >= now) kept.push(item);\n else item.cb?.(new Error(\"Send dropped: queued item expired\"));\n }\n this.sendQueue = kept;\n }\n\n private updateState(state: SocketState): void {\n this.state = state;\n this.onStateChangeCallback?.(state);\n }\n}\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\r\nimport { NotifyScope, NotifyKind } from \"../core/types.js\";\r\nimport { Configuration } from \"../core/configuration.js\";\r\nimport { RecoverableSocket, SocketState } from \"../utils/recoverable-socket.js\";\r\nimport { sleep } from \"@devicelink-workspace/common\";\r\n\r\ntype StartReason =\r\n | \"onStarted\"\r\n | \"config:cache:validated\"\r\n | \"auth:ws:reconnect\"\r\n | \"socket:disconnected\";\r\n\r\nexport class WebSocketOrchestrator implements Orchestrator {\r\n public readonly name = \"websocket-orchestrator\";\r\n\r\n private socket: RecoverableSocket | null = null;\r\n private stopped = false;\r\n\r\n private connectLoopInFlight: Promise<void> | null = null;\r\n\r\n private retryAttempt = 0;\r\n private countdownTimer: NodeJS.Timeout | null = null;\r\n\r\n private lastUrl: string | null = null;\r\n\r\n public onRegister(_ctx: OrchestratorContext): void {}\r\n\r\n public async onStart(ctx: OrchestratorContext): Promise<void> {\r\n ctx.notifier.info(\"WS: orchestrator started\", { scope: NotifyScope.System });\r\n }\r\n\r\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\r\n const config = ctx.engine.configurationContext.configuration;\r\n if (await this.isConnectableToBridge(config, ctx)) {\r\n this.ensureStarted(ctx, \"onStarted\");\r\n }\r\n }\r\n\r\n public async onStop(ctx: OrchestratorContext): Promise<void> {\r\n this.stopped = true;\r\n this.clearCountdown();\r\n\r\n if (this.socket) {\r\n ctx.notifier.info(\"WS: stopping socket (onStop)\", { scope: NotifyScope.System });\r\n this.socket.stop();\r\n this.socket = null;\r\n }\r\n\r\n ctx.notifier.info(\"WS: orchestrator stopped\", { scope: NotifyScope.System });\r\n }\r\n\r\n public async onStopped(): Promise<void> {}\r\n\r\n public handlers() {\r\n const initSocket = async (reason: StartReason, ctx: OrchestratorContext) => {\r\n if (this.stopped) return;\r\n\r\n const config = ctx.engine.configurationContext.configuration;\r\n if (!(await this.isConnectableToBridge(config, ctx))) return;\r\n\r\n this.ensureStarted(ctx, reason);\r\n };\r\n\r\n return {\r\n \"config:cache:validated\": async (_: void, ctx: OrchestratorContext) =>\r\n initSocket(\"config:cache:validated\", ctx),\r\n\r\n \"auth:signout:requested\": async (_: void, ctx: OrchestratorContext) => {\r\n ctx.notifier.info(\"WS: sign-out requested -> disconnecting\");\r\n this.stopped = true;\r\n this.clearCountdown();\r\n this.socket?.stop();\r\n this.socket = null;\r\n },\r\n\r\n \"ws:disconnect\": async (p: { reason?: string }, ctx: OrchestratorContext) => {\r\n ctx.notifier.info(\"WS: disconnect requested\", { scope: NotifyScope.System });\r\n this.stopped = true;\r\n this.clearCountdown();\r\n this.socket?.stop();\r\n this.socket = null;\r\n },\r\n\r\n \"auth:ws:reconnect\": async (_: void, ctx: OrchestratorContext) => {\r\n ctx.notifier.info(\"WS: reconnect requested by auth\", { scope: NotifyScope.System });\r\n\r\n this.retryAttempt = 0;\r\n this.clearCountdown();\r\n\r\n // Fully destroy old socket to prevent its onclose from triggering another connect\r\n if (this.socket) {\r\n this.socket.stop();\r\n this.socket = null;\r\n }\r\n\r\n this.ensureStarted(ctx, \"auth:ws:reconnect\");\r\n },\r\n\r\n // the only sender\r\n \"ws:tx\": async (p: { text: string }, ctx: OrchestratorContext) => {\r\n const ws = this.socket?.getSocket();\r\n if (!ws || ws.readyState !== 1) {\r\n ctx.notifier.info(\"WS: TX dropped (not connected)\", { scope: NotifyScope.System });\r\n return;\r\n }\r\n ws.send(p.text);\r\n },\r\n };\r\n }\r\n\r\n private ensureStarted(ctx: OrchestratorContext, reason: StartReason) {\r\n if (this.connectLoopInFlight) {\r\n ctx.notifier.info(`WS: connect loop already running (reason=${reason})`, { scope: NotifyScope.System });\r\n return;\r\n }\r\n\r\n // Already connected \u2014 skip (auth:ws:reconnect nulls the socket before calling this, so it bypasses this check)\r\n const ws = this.socket?.getSocket();\r\n if (ws && ws.readyState <= 1 /* CONNECTING or OPEN */) {\r\n ctx.notifier.info(`WS: already connected/connecting, skipping (reason=${reason})`, { scope: NotifyScope.System });\r\n return;\r\n }\r\n\r\n this.connectLoopInFlight = this.startOrJoinConnectLoop(ctx, reason).finally(() => {\r\n this.connectLoopInFlight = null;\r\n });\r\n }\r\n\r\n private async startOrJoinConnectLoop(ctx: OrchestratorContext, reason: StartReason): Promise<void> {\r\n this.stopped = false;\r\n\r\n const config = ctx.engine.configurationContext.configuration;\r\n const isConnectable = await this.isConnectableToBridge(config, ctx);\r\n if (!isConnectable) return;\r\n\r\n const url = String(config.bridgeWsUrl);\r\n this.lastUrl = url;\r\n\r\n ctx.notifier.info(`WS: ensure connection (reason=${reason}) url=${url}`, { scope: NotifyScope.System });\r\n\r\n if (!this.socket) {\r\n const sock = new RecoverableSocket(url, {\r\n abortSignal: ctx.signal,\r\n connectionTimeoutMs: 10_000,\r\n heartbeatIntervalMs: 20_000,\r\n pongTimeoutMs: 10_000,\r\n });\r\n this.socket = sock;\r\n\r\n sock.registerOnStateChangeCallback((state) => this.handleStateChange(state, ctx));\r\n\r\n sock.registerOnErrorCallback((error) => {\r\n ctx.notifier.error(`WS: transport error: ${error.message}`);\r\n });\r\n\r\n sock.registerOnConnectedCallback((_ws) => {\r\n if (this.socket !== sock) return; // stale socket \u2014 ignore\r\n this.retryAttempt = 0;\r\n this.clearCountdown();\r\n\r\n ctx.notifier.success(ctx.flags.debug ? `WS: connected (${url})` : `WS: connected`);\r\n ctx.bus.emit(\"ws:connected\", { url, attempt: 0 } as any);\r\n });\r\n\r\n sock.registerOnDisconnectedCallback((code, reasonStr) => {\r\n // Guard against late close events from a replaced socket\r\n if (this.socket !== sock) {\r\n ctx.notifier.info(`WS: ignoring stale disconnect (code=${code})`, { scope: NotifyScope.System });\r\n return;\r\n }\r\n\r\n ctx.notifier.warn(`WS: disconnected code=${code} reason=${reasonStr || \"-\"}`);\r\n ctx.bus.emit(\"ws:disconnected\", { code, reason: reasonStr });\r\n\r\n // Auth-related close: do not auto loop; Auth will refresh and request reconnect\r\n if (code === 4001) {\r\n ctx.notifier.info(\"WS: auth disconnect (4001) -> waiting for auth\", { scope: NotifyScope.System });\r\n return;\r\n }\r\n\r\n // Conflict rejection: stop completely, don't reconnect\r\n if (code === 4011) {\r\n this.stopped = true;\r\n this.socket?.stop();\r\n this.socket = null;\r\n return;\r\n }\r\n\r\n // otherwise keep reconnect loop\r\n this.ensureStarted(ctx, \"socket:disconnected\");\r\n });\r\n\r\n sock.registerOnMessageCallback((data) => {\r\n if (this.socket !== sock) return; // stale socket \u2014 ignore\r\n const text = typeof data === \"string\" ? data : data.toString(\"utf8\");\r\n ctx.bus.emit(\"ws:rx\", { text });\r\n });\r\n }\r\n\r\n while (!this.stopped) {\r\n try {\r\n const attemptNo = this.retryAttempt + 1;\r\n ctx.notifier.info(`WS: connecting attempt #${attemptNo} to ${url}`, { scope: NotifyScope.System, groupKey: 'ws:connecting' });\r\n\r\n ctx.bus.emit(\"ws:connecting\", { url, attempt: attemptNo });\r\n\r\n await this.socket.connect();\r\n return;\r\n } catch (e: any) {\r\n if (this.stopped) return;\r\n\r\n this.retryAttempt += 1;\r\n\r\n const delayMs = this.computeBackoffMs(this.retryAttempt);\r\n const seconds = Math.max(1, Math.ceil(delayMs / 1000));\r\n const errMsg = String(e?.message ?? e ?? \"unknown error\");\r\n\r\n ctx.notifier.warn(\r\n `WS: connect failed (attempt=${this.retryAttempt}) -> retry in ${seconds}s (${errMsg})`,\r\n { scope: NotifyScope.System, category: ['websocket-connect'], groupKey: 'ws:connect-retry' }\r\n );\r\n\r\n ctx.bus.emit(\"ws:retrying\", { retryInSec: seconds, attempt: this.retryAttempt } as any);\r\n this.startCountdown(seconds, ctx);\r\n\r\n await this.interruptibleSleep(delayMs);\r\n }\r\n }\r\n }\r\n\r\n private async isConnectableToBridge(config: Configuration, ctx: OrchestratorContext): Promise<boolean> {\r\n if (!config.device?.id) {\r\n ctx.notifier.error(\"WS: cannot connect: device.id missing\");\r\n return false;\r\n }\r\n if (!config.bridgeWsUrl) {\r\n ctx.notifier.error(\"WS: cannot connect: bridgeWsUrl missing\");\r\n return false;\r\n }\r\n if (!config.device?.keys?.public) {\r\n ctx.notifier.error(\"WS: cannot connect: device public key missing\");\r\n return false;\r\n }\r\n\r\n const refreshRes = await ctx.engine.secrets.get(\"refreshToken\");\r\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\r\n if (!hasRefresh) {\r\n ctx.notifier.warn(\"WS: not connecting (no tokens). Run signin.\");\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private handleStateChange(state: SocketState, ctx: OrchestratorContext): void {\r\n if (state.kind === \"CONNECTING\") ctx.notifier.info(`WS: state CONNECTING (url=${this.lastUrl})`, { scope: NotifyScope.System });\r\n if (state.kind === \"CONNECTED\") ctx.notifier.info(`WS: state CONNECTED (url=${this.lastUrl})`, { scope: NotifyScope.System });\r\n if (state.kind === \"DISCONNECTED\") ctx.notifier.info(`WS: state DISCONNECTED (url=${this.lastUrl})`, { scope: NotifyScope.System });\r\n }\r\n\r\n private computeBackoffMs(attempt: number): number {\r\n const base = Math.min(30_000, 1000 * Math.pow(2, Math.min(attempt - 1, 5)));\r\n const jitter = base * (0.2 * (Math.random() * 2 - 1));\r\n return Math.max(250, Math.floor(base + jitter));\r\n }\r\n\r\n private startCountdown(seconds: number, ctx: OrchestratorContext) {\r\n this.clearCountdown();\r\n\r\n let remaining = seconds;\r\n this.countdownTimer = setInterval(() => {\r\n remaining -= 1;\r\n if (remaining <= 0) {\r\n this.clearCountdown();\r\n return;\r\n }\r\n ctx.bus.emit(\"ws:retrying\", { retryInSec: remaining, attempt: this.retryAttempt } as any);\r\n }, 1000);\r\n }\r\n\r\n private clearCountdown() {\r\n if (this.countdownTimer) {\r\n clearInterval(this.countdownTimer);\r\n this.countdownTimer = null;\r\n }\r\n }\r\n\r\n private async interruptibleSleep(ms: number): Promise<void> {\r\n const step = 100;\r\n const start = Date.now();\r\n while (Date.now() - start < ms) {\r\n if (this.stopped) return;\r\n await sleep(step);\r\n }\r\n }\r\n}\r\n", "import fs from 'node:fs';\r\nimport path from 'node:path';\r\nimport os from 'node:os';\r\nimport { Configuration } from '../core/configuration';\r\nimport defaultTo from 'lodash/defaultTo.js';\r\n\r\nexport class ConfigurationWriter {\r\n /**\r\n * Saves the configuration to the standard config file location.\r\n * Strips any secret fields so they are never persisted to disk.\r\n */\r\n public static save(config: Configuration): string {\r\n const configDir = this.getApplicationConfigFolder();\r\n const configPath = path.join(configDir, 'config.json');\r\n\r\n const safe = this.stripSecrets(config);\r\n fs.mkdirSync(configDir, { recursive: true });\r\n fs.writeFileSync(configPath, JSON.stringify(safe, null, 2), 'utf8');\r\n\r\n return configPath;\r\n }\r\n\r\n private static stripSecrets(config: Configuration): Configuration {\r\n const device = config.device\r\n ? {\r\n id: config.device.id,\r\n name: config.device.name,\r\n tag: config.device.tag,\r\n keys: { public: config.device.keys.public },\r\n }\r\n : undefined;\r\n const tokens = config.tokens\r\n ? { accessTokenExpSec: config.tokens.accessTokenExpSec }\r\n : undefined;\r\n return {\r\n ...config,\r\n device,\r\n tokens,\r\n };\r\n }\r\n\r\n /**\r\n * Gets the application config folder path\r\n * Uses the same logic as ConfigBuilder.getApplicationConfigFolder()\r\n */\r\n private static getApplicationConfigFolder(): string {\r\n const appData = defaultTo(\r\n process.env['APPDATA'],\r\n path.join(os.homedir(), 'AppData', 'Roaming')\r\n );\r\n return path.join(appData, 'DeviceLink');\r\n }\r\n}\r\n", "import { Orchestrator, OrchestratorContext } from \"../core/orchestrator.js\";\nimport { EnginePhase, NotifyScope } from \"../core/types.js\";\nimport { loadConfigCall, LoadConfigInput, type LoadConfigJob } from \"../jobs/loadConfig.js\";\nimport { Configuration } from \"../core/configuration.js\";\nimport { ConfigurationWriter } from \"../utils/configuration.writer.js\";\n\nexport class MainOrchestrator implements Orchestrator {\n public readonly name = \"main-orchestrator\";\n\n constructor() {}\n\n private bootStarted = false;\n\n // --- persistence control (prevents disk spam during frequent refresh) ---\n private saveTimer: NodeJS.Timeout | null = null;\n private saveInFlight: Promise<void> | null = null;\n private latestConfigToSave: Configuration | null = null;\n\n // tune this: 250\u20131000ms is usually nice\n private readonly saveDebounceMs = 500;\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(_ctx: OrchestratorContext): Promise<void> {}\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {}\n\n public async onStop(_ctx: OrchestratorContext): Promise<void> {\n // try to flush pending save on shutdown\n await this.flushSaveOnStop().catch(() => {});\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {}\n\n public handlers() {\n return {\n \"ui:initialized\": async (_ts: number, ctx: OrchestratorContext) => {\n if (this.bootStarted) return;\n this.bootStarted = true;\n\n ctx.engine.setPhase(EnginePhase.Booting);\n ctx.notifier.info(\"Booting...\");\n\n ctx.engine.dispatch(loadConfigCall(new LoadConfigInput()));\n },\n\n /**\n * Centralized disk persistence.\n * Any orchestrator can emit this after calling ctx.engine.applyConfiguration(updated).\n */\n \"config:save:requested\": async (config: Configuration, ctx: OrchestratorContext) => {\n this.latestConfigToSave = config;\n\n // debounce frequent writes (e.g., token refresh)\n if (this.saveTimer){\n clearTimeout(this.saveTimer);\n }\n this.saveTimer = setTimeout(() => {\n void this.performSave(ctx);\n }, this.saveDebounceMs);\n },\n };\n }\n\n private async performSave(ctx: OrchestratorContext): Promise<void> {\n // if a save is already running, let it finish; it will re-check latestConfigToSave afterwards\n if (this.saveInFlight) return;\n\n this.saveInFlight = (async () => {\n while (this.latestConfigToSave) {\n const config = this.latestConfigToSave;\n this.latestConfigToSave = null;\n\n try {\n const configPath = ConfigurationWriter.save(config);\n\n ctx.notifier.info(`Config saved to: ${configPath}`, { scope: NotifyScope.System });\n\n // keep compatibility with your existing listeners\n ctx.bus.emit(\"config:saved\", void 0);\n } catch (e: any) {\n const msg = e?.message ?? String(e);\n ctx.notifier.error(`Failed to save configuration: ${msg}`);\n\n // optional failure event if you want UIs to react\n // ctx.bus.emit(\"configuration:save:failed\", { message: msg });\n }\n }\n })().finally(() => {\n this.saveInFlight = null;\n });\n\n await this.saveInFlight;\n }\n\n private async flushSaveOnStop(): Promise<void> {\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n // cannot access ctx here (stop signature passes ctx but you aren\u2019t using it), so do a best-effort:\n // If you want guaranteed flush with notifier logs, pass ctx to onStop and call performSave(ctx).\n }\n}\n", "import { Orchestrator, OrchestratorContext } from '../core/orchestrator.js';\r\nimport { DispatchStatus, NotifyScope, NotifyKind, EnginePhase } from '../core/types.js';\r\nimport { decodeJwt } from 'jose';\r\nimport crypto from 'node:crypto';\r\nimport { Configuration } from '../core/configuration.js';\r\nimport { Api } from '../api/index.js';\r\nimport { fingerprintFromPublicKeyPem, signConnect } from '@devicelink-workspace/common';\r\nimport { BridgeOutboundMsgSchema } from '@devicelink-workspace/domain';\r\nimport type {\r\n DeviceAuthStartResponse,\r\n DeviceAuthStreamResponse,\r\n ConnectRequest,\r\n SessionInitRequest,\r\n ConnectAck,\r\n SessionInitAck,\r\n DisconnectNoticeResponse,\r\n SessionConflictRequest,\r\n SessionConflictResolveAck,\r\n DeviceAuthRefreshRequest,\r\n DeviceAuthRefreshResponse,\r\n ToolCallRequest,\r\n} from '@devicelink-workspace/domain';\r\nimport type { BaseStorage } from '../../storage/index.js';\r\nimport {\r\n refreshTokensCall,\r\n REFRESH_UNRECOVERABLE_CODES,\r\n RefreshTokensInput,\r\n RefreshTokensOutput,\r\n type RefreshTokensJob,\r\n} from '../jobs/refreshTokens.js';\r\nimport { Scheduler } from '../utils/scheduler.js';\r\n\r\ntype Phase = 'IDLE' | 'CONNECT_SENT' | 'WAIT_SESSION_INIT_ACK' | 'READY';\r\n\r\ntype TokenReason =\r\n | 'boot'\r\n | 'signin'\r\n | 'connect_ack_next'\r\n | 'ws_4001'\r\n | 'timer'\r\n | 'manual'\r\n | 'retry';\r\n\r\nexport class AuthOrchestrator implements Orchestrator {\r\n public readonly name = 'auth-orchestrator';\r\n\r\n private phase: Phase = 'IDLE';\r\n private connectionId: string | null = null;\r\n private sessionId: string | null = null;\r\n private accessToken?: string;\r\n private rejectedByConflict = false;\r\n\r\n private refreshGroupKey = 'auth:refresh';\r\n private refreshCycle = 0;\r\n private refreshScheduler: Scheduler | null = null;\r\n private refreshRetryScheduler: Scheduler | null = null;\r\n private lastRefreshPlan?: { exp: number | null; groupKey: string };\r\n\r\n private refreshInFlight?: Promise<boolean>;\r\n\r\n private conflictTimer: NodeJS.Timeout | null = null;\r\n private pendingConflictRequest: SessionConflictRequest | null = null;\r\n\r\n private signinStarted = false;\r\n\r\n public onRegister(): void {}\r\n\r\n public async onStart(ctx: OrchestratorContext): Promise<void> {\r\n ctx.notifier.info('Auth orchestrator started', { scope: NotifyScope.System });\r\n }\r\n\r\n public async onStop(ctx: OrchestratorContext): Promise<void> {\r\n this.clearTimers();\r\n this.resetConnectionState();\r\n ctx.notifier.info('Auth orchestrator stopped', { scope: NotifyScope.System });\r\n }\r\n\r\n public async onStarted(): Promise<void> {}\r\n public async onStopped(): Promise<void> {}\r\n\r\n public handlers() {\r\n return {\r\n 'config:loaded': this.onEventConfigLoaded.bind(this),\r\n 'config:cache:validated': this.onEventConfigCacheValidated.bind(this),\r\n\r\n 'auth:signin:requested': this.onEventAuthSigninRequested.bind(this),\r\n\r\n 'auth:signin:completed': async (_: void, ctx: OrchestratorContext) => {\r\n ctx.notifier.info(\r\n 'Auth: signin completed; requesting ws reconnect',\r\n { scope: NotifyScope.System },\r\n );\r\n this.rejectedByConflict = false;\r\n\r\n // Stop any stale retry scheduler from a prior failed refresh (e.g. boot)\r\n // to prevent it from firing after signin and causing a duplicate reconnect.\r\n if (this.refreshRetryScheduler) {\r\n this.refreshRetryScheduler.stop();\r\n this.refreshRetryScheduler = null;\r\n }\r\n\r\n this.ensureAccessExpPersisted(ctx, 'signin');\r\n await this.ensureRefreshScheduling(ctx, 'signin');\r\n ctx.bus.emit('auth:ws:reconnect', void 0);\r\n },\r\n\r\n 'auth:signout:requested': async (_: void, ctx: OrchestratorContext) => {\r\n ctx.notifier.info('Signing out\u2026');\r\n\r\n // 1. Stop refresh scheduler\r\n this.clearTimers();\r\n\r\n // 2. Clear in-memory access token\r\n this.accessToken = undefined;\r\n\r\n // 3. Remove refresh token from secure storage (if exists)\r\n try {\r\n await ctx.engine.secrets.delete('refreshToken');\r\n } catch {\r\n // ignore if not present\r\n }\r\n\r\n // 4. Clear tokens from configuration\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const updated: Configuration = {\r\n ...cfg,\r\n tokens: undefined,\r\n };\r\n\r\n ctx.engine.applyConfiguration(updated);\r\n ctx.bus.emit('config:save:requested', updated);\r\n\r\n // 5. Reset connection state\r\n this.resetConnectionState();\r\n\r\n // 6. Reset engine phase to not-authenticated\r\n ctx.engine.setPhase(EnginePhase.Idle);\r\n\r\n // 7. Inform system that tokens changed (cleared)\r\n ctx.bus.emit('auth:tokens:updated', {\r\n accessToken: '',\r\n refreshToken: '',\r\n expSec: undefined,\r\n });\r\n\r\n // 8. Explicitly disconnect WebSocket\r\n ctx.bus.emit('ws:disconnect', { reason: 'signout' });\r\n\r\n // 9. Notify UI\r\n ctx.notifier.success('Signed out successfully');\r\n },\r\n\r\n 'auth:session_conflict:resolve': async (\r\n p: { choice: 'USE_NEW' | 'KEEP_OLD' },\r\n ctx: OrchestratorContext,\r\n ) => {\r\n this.sendSessionConflictResolve(ctx, p.choice);\r\n },\r\n\r\n 'ws:connected': async (_: unknown, ctx: OrchestratorContext) => {\r\n this.resetConnectionState();\r\n\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\r\n const hasAccess = !!this.accessToken;\r\n\r\n ctx.notifier.info(\r\n `Auth: ws connected; tokens access=${hasAccess} refresh=${hasRefresh}`,\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n if (!hasAccess && !hasRefresh) {\r\n ctx.notifier.warn('Auth: no tokens; run signin');\r\n return;\r\n }\r\n\r\n await this.sendConnect(ctx);\r\n },\r\n\r\n 'ws:rx': async (p: { text: string }, ctx: OrchestratorContext) => {\r\n this.onInbound(p.text, ctx);\r\n },\r\n\r\n 'ws:disconnected': async (\r\n p: { code: number; reason?: string },\r\n ctx: OrchestratorContext,\r\n ) => {\r\n ctx.notifier.warn(\r\n `Auth: ws disconnected code=${p.code} reason=${p.reason ?? '-'}`,\r\n { scope: NotifyScope.System },\r\n );\r\n this.resetConnectionState();\r\n\r\n // Rejected by conflict resolution \u2014 stop reconnecting\r\n if (p.code === 4011) {\r\n ctx.notifier.warn(\r\n 'Connection rejected - another device is active on this workspace. Run \"signin\" to try again.',\r\n );\r\n this.rejectedByConflict = true;\r\n ctx.bus.emit('ws:disconnect', { reason: 'REPLACEMENT_REJECTED' });\r\n return;\r\n }\r\n\r\n if (p.code === 4001) {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value) {\r\n ctx.notifier.warn(\r\n 'Auth: token invalid and no refresh; please sign in',\r\n );\r\n await this.teardownTokens(ctx, 'AUTH_REQUIRED');\r\n return;\r\n }\r\n\r\n const ok = await this.requestRefresh(ctx, {\r\n force: true,\r\n reason: 'ws_4001',\r\n });\r\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\r\n }\r\n },\r\n };\r\n }\r\n\r\n // --- boot path unchanged except it must schedule refresh always ---\r\n private async onEventConfigLoaded(\r\n config: Configuration,\r\n ctx: OrchestratorContext,\r\n ) {\r\n ctx.notifier.info(\r\n 'Initializing with cached configuration',\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n if (!config.device?.id) {\r\n ctx.notifier.error('Device ID is not available');\r\n return;\r\n }\r\n if (!config.device.keys?.public) {\r\n ctx.notifier.error(\r\n 'Device public key is not available',\r\n );\r\n return;\r\n }\r\n\r\n ctx.bus.emit('config:cache:validated', void 0);\r\n }\r\n\r\n private async onEventConfigCacheValidated(_: void, ctx: OrchestratorContext) {\r\n this.ensureAccessExpPersisted(ctx, 'boot');\r\n await this.ensureRefreshScheduling(ctx, 'boot');\r\n\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n const hasRefresh = !!refreshRes.ok && !!refreshRes.value;\r\n const hasAccess = !!this.accessToken;\r\n const accessOk = this.isAccessLikelyUsable(ctx);\r\n\r\n ctx.notifier.info(\r\n `Auth: cache validated; access=${hasAccess} refresh=${hasRefresh} accessOk=${accessOk}`,\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n if (!hasAccess && !hasRefresh) {\r\n ctx.notifier.warn('Auth: not signed in; run signin');\r\n return;\r\n }\r\n\r\n // Do NOT emit auth:ws:reconnect here \u2014 the WS orchestrator already handles\r\n // config:cache:validated directly and will connect on its own.\r\n // auth:ws:reconnect is reserved for forced reconnects (signin, token refresh)\r\n // where the WS must tear down and re-establish with fresh credentials.\r\n }\r\n\r\n private isAccessLikelyUsable(ctx: OrchestratorContext): boolean {\r\n const jwt = this.accessToken;\r\n if (!jwt) return false;\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const exp = cfg?.tokens?.accessTokenExpSec ?? this.tryDecodeExp(jwt);\r\n if (!exp) return true;\r\n const now = Math.floor(Date.now() / 1000);\r\n return exp > now;\r\n }\r\n\r\n // --- signin path unchanged (kept from your code) ---\r\n private async waitForApproval(\r\n api: Api,\r\n startResponse: DeviceAuthStartResponse,\r\n ctx: OrchestratorContext,\r\n ): Promise<DeviceAuthStreamResponse | null> {\r\n const deadline = Date.now() + startResponse.expires_in * 1000;\r\n ctx.notifier.info(\r\n 'Waiting for approval... (streaming)',\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n try {\r\n return await api.deviceAuthStream({\r\n deviceCode: startResponse.device_code,\r\n timeoutMs: Math.max(1000, deadline - Date.now()),\r\n signal: ctx.signal,\r\n });\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : String(e);\r\n ctx.notifier.error(\r\n `Failed to wait for approval: ${msg}`,\r\n );\r\n return null;\r\n }\r\n }\r\n\r\n private async onEventAuthSigninRequested(_: void, ctx: OrchestratorContext) {\r\n if (this.signinStarted) {\r\n ctx.notifier.warn('Sign-in already in progress', { scope: NotifyScope.System });\r\n return;\r\n }\r\n\r\n this.signinStarted = true;\r\n\r\n try {\r\n const configuration = ctx.engine.configurationContext.configuration;\r\n\r\n if (!configuration.controlBaseUrl) {\r\n ctx.notifier.error('Control base URL is not set');\r\n return;\r\n }\r\n if (!configuration.device?.id) {\r\n ctx.notifier.error('Device ID is not available');\r\n return;\r\n }\r\n if (!configuration.device.keys?.public) {\r\n ctx.notifier.error(\r\n 'Device public key is not available',\r\n );\r\n return;\r\n }\r\n\r\n const privateRes = await ctx.engine.secrets.get('devicePrivateKey');\r\n if (!privateRes.ok || !privateRes.value) {\r\n ctx.notifier.error(\r\n 'Device private key is not available (secret storage)',\r\n );\r\n return;\r\n }\r\n const privateKeyPem = privateRes.value;\r\n\r\n const deviceName = configuration.device.name as string;\r\n const platform = process.platform;\r\n const publicKeyPem = configuration.device.keys.public;\r\n\r\n const fingerprint = fingerprintFromPublicKeyPem(publicKeyPem);\r\n const api = new Api(configuration, ctx.notifier);\r\n\r\n ctx.notifier.info(\r\n 'Starting device authentication...',\r\n );\r\n\r\n const startResponse = await api.deviceAuthStart({\r\n device_id: configuration.device.id,\r\n device_name: deviceName,\r\n platform,\r\n public_key_pem: publicKeyPem,\r\n });\r\n\r\n ctx.notifier.info('DeviceLink sign-in');\r\n ctx.notifier.info(\r\n `User code: ${startResponse.user_code}`,\r\n );\r\n ctx.notifier.info(\r\n `Device fingerprint: ${fingerprint}`,\r\n );\r\n ctx.notifier.info(\r\n `Verification URL: ${startResponse.verification_uri_complete}`,\r\n );\r\n\r\n const streamResp = await this.waitForApproval(api, startResponse, ctx);\r\n if (!streamResp) return;\r\n\r\n if ('error' in streamResp) {\r\n if (streamResp.error === 'access_denied') {\r\n ctx.notifier.error('Sign-in denied in browser.');\r\n return;\r\n }\r\n if (streamResp.error === 'expired_token') {\r\n ctx.notifier.error(\r\n 'Sign-in expired. Run `signin` again.',\r\n );\r\n return;\r\n }\r\n ctx.notifier.error(\r\n `Unexpected error: ${(streamResp as { error: string }).error}`,\r\n );\r\n return;\r\n }\r\n\r\n if (streamResp.status !== 'approved') {\r\n ctx.notifier.error(\r\n `Unexpected status: ${streamResp.status}`,\r\n );\r\n return;\r\n }\r\n\r\n if (streamResp.needs_proof) {\r\n ctx.notifier.info(\r\n 'Sending proof-of-possession signature...',\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n const privKeyObj = crypto.createPrivateKey(privateKeyPem);\r\n const challengeBytes = Buffer.from(\r\n startResponse.challenge,\r\n 'base64url',\r\n );\r\n const sig = crypto.sign(null, challengeBytes, privKeyObj);\r\n const signatureB64 = sig.toString('base64');\r\n\r\n await api.deviceAuthProve({\r\n device_code: startResponse.device_code,\r\n challenge_id: startResponse.challenge_id,\r\n challenge: startResponse.challenge,\r\n signature_b64: signatureB64,\r\n });\r\n\r\n ctx.notifier.info('Proof-of-possession verified', { scope: NotifyScope.System });\r\n }\r\n\r\n ctx.notifier.info('Fetching tokens...', { scope: NotifyScope.System });\r\n\r\n const tokenResp = await api.deviceAuthToken({\r\n device_code: startResponse.device_code,\r\n });\r\n\r\n const deviceTag = 'tag'; // computeDeviceTag(...)\r\n\r\n await ctx.engine.secrets.set('refreshToken', tokenResp.refresh_token);\r\n this.accessToken = tokenResp.access_token;\r\n\r\n const expFromJwt = this.tryDecodeExp(tokenResp.access_token);\r\n const updatedConfig: Configuration = {\r\n ...configuration,\r\n controlBaseUrl: configuration.controlBaseUrl,\r\n device: {\r\n ...configuration.device,\r\n id: tokenResp.device_id,\r\n name: deviceName,\r\n tag: deviceTag,\r\n keys: {\r\n public: publicKeyPem,\r\n },\r\n },\r\n tokens: {\r\n ...(configuration.tokens ?? {}),\r\n accessTokenExpSec: expFromJwt ?? undefined,\r\n },\r\n };\r\n\r\n ctx.engine.applyConfiguration(updatedConfig);\r\n ctx.bus.emit('config:save:requested', updatedConfig);\r\n\r\n ctx.bus.emit('auth:signin:completed', void 0);\r\n\r\n ctx.notifier.success('Signed in successfully \u2705');\r\n } catch (e: any) {\r\n if (['ECONNREFUSED', 'ENOTFOUND', 'ETIMEDOUT'].includes(e?.code)) {\r\n ctx.notifier.error(\r\n `Network error: ${e?.message ?? String(e)}`,\r\n );\r\n return;\r\n }\r\n ctx.notifier.error(\r\n `Sign-in failed: ${e?.message ?? String(e)}`,\r\n );\r\n } finally {\r\n this.signinStarted = false;\r\n }\r\n }\r\n\r\n // ---------------------------\r\n // Outbound steps\r\n // ---------------------------\r\n\r\n // --- ws protocol steps ---\r\n private async sendConnect(ctx: OrchestratorContext): Promise<void> {\r\n const config = ctx.engine.configurationContext.configuration;\r\n const device = config.device;\r\n\r\n const privateRes = await ctx.engine.secrets.get('devicePrivateKey');\r\n if (!device?.id || !privateRes.ok || !privateRes.value) {\r\n ctx.notifier.warn(\r\n 'Cannot connect: device not configured',\r\n );\r\n return;\r\n }\r\n const privateKeyPem = privateRes.value;\r\n\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n const refreshToken = refreshRes.ok ? refreshRes.value : undefined;\r\n\r\n const ts = Date.now();\r\n const nonce = crypto.randomBytes(16).toString('base64url');\r\n const sig = signConnect({\r\n deviceId: device.id,\r\n ts,\r\n nonce,\r\n privateKeyPem,\r\n });\r\n\r\n const connectMessage: ConnectRequest = {\r\n type: 'connect',\r\n device_id: device.id,\r\n agent_version: String(config.version ?? '1'),\r\n ts,\r\n nonce,\r\n sig,\r\n platform: process.platform,\r\n hostname: device.name,\r\n device_tag: device.tag,\r\n access_token: this.accessToken,\r\n refresh_token: refreshToken,\r\n public_key_pem: device.keys.public,\r\n };\r\n\r\n this.phase = 'CONNECT_SENT';\r\n ctx.notifier.info('Auth: sending connect', { scope: NotifyScope.System });\r\n this.send(ctx, connectMessage);\r\n }\r\n\r\n private async sendSessionInit(\r\n ctx: OrchestratorContext,\r\n ack: ConnectAck,\r\n ): Promise<void> {\r\n const config = ctx.engine.configurationContext.configuration;\r\n const device = config.device;\r\n if (!device?.id || !this.sessionId) {\r\n ctx.notifier.error('Cannot send session_init: device ID or session ID not available');\r\n return;\r\n }\r\n\r\n const msg: SessionInitRequest = {\r\n type: 'session_init',\r\n device_id: device.id,\r\n session_id: this.sessionId,\r\n };\r\n\r\n this.phase = 'WAIT_SESSION_INIT_ACK';\r\n ctx.notifier.info('Auth: sending session_init', { scope: NotifyScope.System });\r\n this.send(ctx, msg);\r\n }\r\n\r\n // --- inbound handling ---\r\n private onInbound(text: string, ctx: OrchestratorContext): void {\r\n let obj: unknown;\r\n try {\r\n obj = JSON.parse(text);\r\n } catch (e: any) {\r\n ctx.notifier.error('Unexpected message format');\r\n return;\r\n }\r\n\r\n const parsed = BridgeOutboundMsgSchema.safeParse(obj);\r\n if (!parsed.success) {\r\n const message = parsed.error.message;\r\n ctx.notifier.error(`Unexpected message format: ${message}`);\r\n return;\r\n }\r\n\r\n const msg = parsed.data;\r\n\r\n switch (msg.type) {\r\n case 'connect_ack':\r\n ctx.bus.emit('auth:connect_ack', msg);\r\n void this.onConnectAck(ctx, msg);\r\n return;\r\n\r\n case 'session_init_ack':\r\n ctx.bus.emit('auth:session_init_ack', msg);\r\n this.onSessionInitAck(ctx, msg);\r\n return;\r\n\r\n case 'disconnect_notice':\r\n this.onDisconnectNotice(ctx, msg);\r\n return;\r\n\r\n case 'session_conflict':\r\n ctx.bus.emit('auth:session_conflict', msg);\r\n void this.handleSessionConflict(ctx, msg);\r\n return;\r\n\r\n case 'quiesce':\r\n void this.handleQuiesce(ctx, msg);\r\n return;\r\n\r\n default:\r\n return;\r\n }\r\n }\r\n\r\n async handleSessionConflict(\r\n ctx: OrchestratorContext,\r\n msg: SessionConflictRequest,\r\n ): Promise<void> {\r\n if (this.conflictTimer) {\r\n clearTimeout(this.conflictTimer);\r\n this.conflictTimer = null;\r\n }\r\n this.pendingConflictRequest = msg;\r\n\r\n // Notify user about the conflict\r\n ctx.notifier.warn(\r\n `Another device is already connected to this workspace. Type \"replace\" to disconnect it, or this connection will be rejected in ${Math.round(msg.deadline_ms / 1000)}s.`,\r\n );\r\n\r\n const deadlineMs = Math.min(msg.deadline_ms, 15_000);\r\n this.conflictTimer = setTimeout(() => {\r\n this.conflictTimer = null;\r\n if (this.pendingConflictRequest?.new_session_id === msg.new_session_id) {\r\n ctx.notifier.info('No response - keeping existing device connected.');\r\n this.sendSessionConflictResolve(ctx, 'KEEP_OLD');\r\n }\r\n }, deadlineMs);\r\n }\r\n\r\n private async handleQuiesce(\r\n ctx: OrchestratorContext,\r\n msg: { session_id: string; reason: string; deadline_ms: number },\r\n ): Promise<void> {\r\n ctx.notifier.warn(\r\n `This device is being replaced by another connection. Finishing in-flight operations...`,\r\n );\r\n\r\n // Check if there are active jobs running\r\n const hasActiveJobs = ctx.engine.hasRunningJobs?.() ?? false;\r\n\r\n if (hasActiveJobs) {\r\n // Wait for jobs to finish, up to deadline\r\n const deadline = Math.min(msg.deadline_ms - 2000, 12_000); // leave 2s buffer\r\n const start = Date.now();\r\n while (Date.now() - start < deadline) {\r\n if (!(ctx.engine.hasRunningJobs?.() ?? false)) break;\r\n await new Promise((r) => setTimeout(r, 500));\r\n }\r\n }\r\n\r\n // Send quiesce_ack - tell bridge we're ready to disconnect\r\n const status = (ctx.engine.hasRunningJobs?.() ?? false) ? 'BUSY' : 'IDLE';\r\n this.send(ctx, {\r\n type: 'quiesce_ack',\r\n session_id: msg.session_id,\r\n status,\r\n });\r\n\r\n ctx.notifier.info('Device replaced by new connection. Disconnecting.');\r\n this.socket?.stop();\r\n }\r\n\r\n sendSessionConflictResolve(\r\n ctx: OrchestratorContext,\r\n choice: 'USE_NEW' | 'KEEP_OLD',\r\n ): void {\r\n const req = this.pendingConflictRequest;\r\n if (!req) return;\r\n if (this.conflictTimer) {\r\n clearTimeout(this.conflictTimer);\r\n this.conflictTimer = null;\r\n }\r\n this.pendingConflictRequest = null;\r\n\r\n this.send(ctx, {\r\n type: 'session_conflict_resolve',\r\n device_id: req.device_id,\r\n new_session_id: req.new_session_id,\r\n choice,\r\n });\r\n }\r\n\r\n private async onConnectAck(\r\n ctx: OrchestratorContext,\r\n ack: ConnectAck,\r\n ): Promise<void> {\r\n if (!ack.ok) {\r\n ctx.notifier.error(\r\n `Connect rejected: ${ack.error.code} ${ack.error.message}`,\r\n );\r\n this.phase = 'IDLE';\r\n return;\r\n }\r\n\r\n this.sessionId = ack.session_id;\r\n\r\n const accessStatus = ack.auth.access_token;\r\n ctx.notifier.info(\r\n `Auth: connect_ack ok auth.access=${accessStatus} next=[${ack.next.join(',')}]`,\r\n { scope: NotifyScope.System },\r\n );\r\n\r\n // 1) honor server next\r\n if (ack.next.includes('refresh_access_token')) {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value) {\r\n ctx.notifier.warn(\r\n 'Auth: server requested refresh but no refresh token; please sign in',\r\n );\r\n await this.teardownTokens(ctx, 'NO_REFRESH_TOKEN');\r\n return;\r\n }\r\n\r\n const ok = await this.requestRefresh(ctx, {\r\n force: true,\r\n reason: 'connect_ack_next',\r\n });\r\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\r\n else\r\n ctx.notifier.warn(\r\n 'Auth: refresh failed; please sign in',\r\n );\r\n\r\n return;\r\n }\r\n\r\n if (ack.next.includes('session_init')) {\r\n await this.sendSessionInit(ctx, ack);\r\n return;\r\n }\r\n\r\n // 2) fallback\r\n if (accessStatus === 'invalid' || accessStatus === 'missing') {\r\n ctx.notifier.warn(\r\n 'Auth: access token invalid; please sign in again',\r\n );\r\n await this.teardownTokens(ctx, 'INVALID_ACCESS');\r\n return;\r\n }\r\n\r\n ctx.notifier.warn(\r\n 'Auth: connect_ack had no next; staying idle',\r\n { scope: NotifyScope.System },\r\n );\r\n }\r\n\r\n private onSessionInitAck(\r\n ctx: OrchestratorContext,\r\n ack: SessionInitAck,\r\n ): void {\r\n if (!ack.ok) {\r\n ctx.notifier.error(\r\n `Session init failed: ${ack.error.code} ${ack.error.message}`,\r\n );\r\n this.phase = 'IDLE';\r\n return;\r\n }\r\n\r\n this.sessionId = ack.session_id;\r\n this.phase = 'READY';\r\n\r\n ctx.notifier.success(`Session ready (${ack.mode})`);\r\n\r\n void this.ensureRefreshScheduling(ctx, 'manual');\r\n\r\n // Honor server's next array - emit events for meta-data orchestrator\r\n if (ack.next) {\r\n if (ack.next.includes('tools_publish')) {\r\n ctx.bus.emit('meta:data:requested:tools', void 0);\r\n }\r\n if (ack.next.includes('directories_publish')) {\r\n ctx.bus.emit('meta:data:requested:directories', void 0);\r\n }\r\n }\r\n }\r\n\r\n private onDisconnectNotice(\r\n ctx: OrchestratorContext,\r\n msg: DisconnectNoticeResponse,\r\n ) {\r\n ctx.notifier.warn(\r\n `Server disconnect_notice: ${msg.reason} (code=${msg.code})`,\r\n );\r\n }\r\n\r\n // --- refresh via job only ---\r\n private async requestRefresh(\r\n ctx: OrchestratorContext,\r\n opts: { force: boolean; reason: TokenReason },\r\n ): Promise<boolean> {\r\n if (this.refreshInFlight) return this.refreshInFlight;\r\n\r\n this.refreshInFlight = (async () => {\r\n try {\r\n return await this.withTimeout(\r\n this.dispatchRefreshJob(ctx, opts),\r\n 60_000,\r\n 'Refresh operation',\r\n );\r\n } catch (error) {\r\n if (error instanceof Error && error.message.includes('timed out')) {\r\n ctx.notifier.error(\r\n `Auth: refresh timed out: ${error.message}`,\r\n { category: ['token-refresh'], groupKey: 'auth:refresh-failure' },\r\n );\r\n }\r\n throw error;\r\n } finally {\r\n this.refreshInFlight = undefined;\r\n }\r\n })();\r\n\r\n return this.refreshInFlight;\r\n }\r\n\r\n private async withTimeout<T>(\r\n promise: Promise<T>,\r\n timeoutMs: number,\r\n operation: string,\r\n ): Promise<T> {\r\n return Promise.race([\r\n promise,\r\n new Promise<T>((_, reject) => {\r\n setTimeout(() => {\r\n reject(new Error(`${operation} timed out after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n }),\r\n ]);\r\n }\r\n\r\n private async dispatchRefreshJob(\r\n ctx: OrchestratorContext,\r\n opts: { force: boolean; reason: TokenReason },\r\n ): Promise<boolean> {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value) return false;\r\n\r\n if (!opts.force) {\r\n const check = await this.shouldRefreshNow(ctx);\r\n if (!check.ok) {\r\n ctx.notifier.info(\r\n `Auth: skip refresh (${check.reason})`,\r\n { scope: NotifyScope.System, category: ['token-refresh'] },\r\n );\r\n return false;\r\n }\r\n }\r\n\r\n ctx.notifier.info(\r\n `Auth: dispatch refresh job (${opts.reason})`,\r\n { scope: NotifyScope.System, category: ['token-refresh'] },\r\n );\r\n\r\n const call = refreshTokensCall(new RefreshTokensInput(opts.reason));\r\n const out = await ctx.engine.dispatch(call);\r\n\r\n ctx.notifier.info(\r\n `Auth: refresh job dispatch completed (status=${out.status})`,\r\n { scope: NotifyScope.System, category: ['token-refresh'] },\r\n );\r\n\r\n if (out.status !== DispatchStatus.Success) {\r\n const msg = out.error?.message ?? 'Unknown error';\r\n ctx.notifier.error(\r\n `Auth: refresh job failed: ${msg}`,\r\n { category: ['token-refresh'], groupKey: 'auth:refresh-failure' },\r\n );\r\n const output = out.output as RefreshTokensOutput | undefined;\r\n if (output?.errorCode && REFRESH_UNRECOVERABLE_CODES.includes(output.errorCode as typeof REFRESH_UNRECOVERABLE_CODES[number])) {\r\n await this.teardownTokens(ctx, output.errorCode);\r\n return false;\r\n }\r\n this.scheduleRefreshRetry(ctx, opts.reason, output?.retryAfterSec);\r\n return false;\r\n }\r\n\r\n const output: RefreshTokensOutput = out.output as RefreshTokensOutput;\r\n\r\n if (!output.ok || !output.accessToken) {\r\n const err = output.error ?? 'Unknown refresh failure';\r\n ctx.notifier.error(`Auth: refresh failed: ${err}`, { category: ['token-refresh'], groupKey: 'auth:refresh-failure' });\r\n if (output.errorCode && REFRESH_UNRECOVERABLE_CODES.includes(output.errorCode as typeof REFRESH_UNRECOVERABLE_CODES[number])) {\r\n await this.teardownTokens(ctx, output.errorCode);\r\n return false;\r\n }\r\n this.scheduleRefreshRetry(ctx, opts.reason, output.retryAfterSec);\r\n return false;\r\n }\r\n\r\n this.accessToken = output.accessToken;\r\n this.persistTokens(ctx, output.accessToken, output.expiresInSec);\r\n await this.ensureRefreshScheduling(ctx, 'manual');\r\n\r\n ctx.bus.emit('auth:tokens:updated', {\r\n accessToken: output.accessToken,\r\n refreshToken: output.refreshToken ?? '',\r\n expSec:\r\n ctx.engine.configurationContext.configuration.tokens?.accessTokenExpSec,\r\n });\r\n\r\n return true;\r\n }\r\n\r\n private scheduleRefreshRetry(ctx: OrchestratorContext, reason: TokenReason, retryAfterSec?: number) {\r\n if (this.refreshRetryScheduler) {\r\n this.refreshRetryScheduler.stop();\r\n }\r\n\r\n const delayMs = this.computeRefreshRetryMs(ctx, reason, retryAfterSec);\r\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\r\n\r\n this.refreshRetryScheduler = new Scheduler()\r\n .schedule(() => {\r\n void this.requestRefresh(ctx, { force: true, reason: 'retry' }).then(\r\n (ok) => {\r\n if (ok) ctx.bus.emit('auth:ws:reconnect', void 0);\r\n },\r\n );\r\n }, sec)\r\n .start();\r\n }\r\n\r\n /**\r\n * Computes delay in ms for the next refresh retry, and logs it.\r\n * If retryAfterSec is valid (e.g. from 429 Retry-After), uses that (clamped by config);\r\n * otherwise uses default backoff (base + jitter, cap by config).\r\n */\r\n private computeRefreshRetryMs(\r\n ctx: OrchestratorContext,\r\n reason: TokenReason,\r\n retryAfterSec?: number,\r\n ): number {\r\n const loader = ctx.engine.configurationContext.loader;\r\n const retryAfterMinSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_RETRY_AFTER_MIN_SEC',\r\n { defaultValue: 1 },\r\n );\r\n const retryAfterMaxSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_RETRY_AFTER_MAX_SEC',\r\n { defaultValue: 300 },\r\n );\r\n const retryBaseSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_RETRY_BASE_SEC',\r\n { defaultValue: 2 },\r\n );\r\n const retryJitterSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_RETRY_JITTER_SEC',\r\n { defaultValue: 1 },\r\n );\r\n const retryMaxSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_RETRY_MAX_SEC',\r\n { defaultValue: 30 },\r\n );\r\n\r\n const valid = typeof retryAfterSec === 'number' && Number.isFinite(retryAfterSec) && retryAfterSec >= 0;\r\n\r\n if (valid) {\r\n const delayMs = Math.min(\r\n retryAfterMaxSec * 1000,\r\n Math.max(retryAfterMinSec * 1000, retryAfterSec! * 1000),\r\n );\r\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\r\n ctx.notifier.warn(\r\n `Auth: refresh retry scheduled in ${sec}s (honoring Retry-After, ${reason})`,\r\n { scope: NotifyScope.System, category: ['token-refresh'], groupKey: 'auth:refresh-retry' },\r\n );\r\n return delayMs;\r\n }\r\n\r\n const delayMs = Math.min(\r\n retryMaxSec * 1000,\r\n retryBaseSec * 1000 + Math.floor(Math.random() * (retryJitterSec + 1)) * 1000,\r\n );\r\n const sec = Math.max(1, Math.ceil(delayMs / 1000));\r\n ctx.notifier.warn(\r\n `Auth: refresh retry scheduled in ${sec}s (${reason})`,\r\n { scope: NotifyScope.System, category: ['token-refresh'], groupKey: 'auth:refresh-retry' },\r\n );\r\n return delayMs;\r\n }\r\n\r\n // --- scheduling ---\r\n private async ensureRefreshScheduling(\r\n ctx: OrchestratorContext,\r\n reason: TokenReason,\r\n ) {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value) return;\r\n\r\n if (this.accessToken && !ctx.engine.configurationContext.configuration.tokens?.accessTokenExpSec) {\r\n this.ensureAccessExpPersisted(ctx, reason);\r\n }\r\n\r\n // Cancel any stale retry scheduler \u2014 we're establishing a fresh schedule\r\n if (this.refreshRetryScheduler) {\r\n this.refreshRetryScheduler.stop();\r\n this.refreshRetryScheduler = null;\r\n }\r\n\r\n this.scheduleSilentRefresh(ctx, reason);\r\n }\r\n\r\n private async scheduleSilentRefresh(ctx: OrchestratorContext, reason: TokenReason) {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value) return;\r\n\r\n if (this.refreshScheduler) this.refreshScheduler.stop();\r\n\r\n const loader = ctx.engine.configurationContext.loader;\r\n const minDelaySec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_MIN_DELAY_SEC',\r\n { defaultValue: 2 },\r\n );\r\n\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const jwt = this.accessToken;\r\n const exp =\r\n cfg.tokens?.accessTokenExpSec ?? (jwt ? this.tryDecodeExp(jwt) : null);\r\n\r\n const plannedExp = exp ?? null;\r\n const groupKey = this.getRefreshGroupKey(ctx);\r\n\r\n if (\r\n this.lastRefreshPlan &&\r\n this.lastRefreshPlan.exp === plannedExp &&\r\n this.lastRefreshPlan.groupKey === groupKey\r\n ) {\r\n // already scheduled/logged this plan \u2192 don\u2019t duplicate\r\n return;\r\n }\r\n\r\n this.lastRefreshPlan = { exp: plannedExp, groupKey };\r\n\r\n // \uD83D\uDD01 local helper captures everything it needs\r\n const start = (opts: {\r\n delaySec: number;\r\n force: boolean;\r\n log?: (remainingSec: number) => void;\r\n }) => {\r\n let s = new Scheduler().schedule(() => {\r\n void this.requestRefresh(ctx, {\r\n force: opts.force,\r\n reason: 'timer',\r\n }).then((ok) => {\r\n if (ok) {\r\n ctx.notifier.success(\r\n 'Auth: refresh completed',\r\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\r\n );\r\n }\r\n });\r\n }, opts.delaySec);\r\n\r\n if (opts.log) {\r\n s = s.onStep((_step, remainingSec) => opts.log!(remainingSec));\r\n }\r\n\r\n this.refreshScheduler = s.start();\r\n };\r\n\r\n // \u2500\u2500 Case 1: no exp \u2192 minimal delay, forced refresh\r\n if (!exp) {\r\n ctx.notifier.info(\r\n `Auth: no exp; scheduling refresh in ${minDelaySec}s [${reason}]`,\r\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\r\n );\r\n\r\n start({\r\n delaySec: minDelaySec,\r\n force: true,\r\n });\r\n\r\n return;\r\n }\r\n\r\n // \u2500\u2500 Case 2: exp-based scheduling with margin + jitter\r\n const now = Math.floor(Date.now() / 1000);\r\n const marginSec = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_MARGIN_SEC',\r\n { defaultValue: 5 },\r\n );\r\n const jitterSecMax = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_JITTER_SEC',\r\n { defaultValue: 2 },\r\n );\r\n const jitter =\r\n jitterSecMax > 0 ? Math.floor(Math.random() * (jitterSecMax + 1)) : 0;\r\n\r\n const targetSec = exp - marginSec - jitter;\r\n const refreshInSec = Math.max(minDelaySec, targetSec - now);\r\n\r\n ctx.notifier.info(\r\n `Auth: refresh scheduled in ${refreshInSec}s (exp=${exp} now=${now} margin=${marginSec} jitter=${jitter}) [${reason}]`,\r\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\r\n );\r\n\r\n start({\r\n delaySec: refreshInSec,\r\n force: false,\r\n log: (remainingSec) => {\r\n ctx.notifier.info(\r\n `Auth: refresh scheduled in ${remainingSec}s (exp=${exp} now=${now} margin=${marginSec} jitter=${jitter}) [${reason}]`,\r\n { scope: NotifyScope.System, groupKey, category: ['token-refresh'] },\r\n );\r\n },\r\n });\r\n }\r\n\r\n private getRefreshGroupKey(ctx: OrchestratorContext): string {\r\n this.refreshCycle++;\r\n return `${this.refreshGroupKey}:${this.refreshCycle}`;\r\n }\r\n\r\n private async shouldRefreshNow(ctx: OrchestratorContext): Promise<{\r\n ok: boolean;\r\n reason: string;\r\n }> {\r\n const refreshRes = await ctx.engine.secrets.get('refreshToken');\r\n if (!refreshRes.ok || !refreshRes.value)\r\n return { ok: false, reason: 'no_refresh_token' };\r\n\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const jwt = this.accessToken;\r\n const exp =\r\n cfg.tokens?.accessTokenExpSec ?? (jwt ? this.tryDecodeExp(jwt) : null);\r\n if (!exp) return { ok: true, reason: 'no_exp_assume_refresh' };\r\n\r\n const now = Math.floor(Date.now() / 1000);\r\n const loader = ctx.engine.configurationContext.loader;\r\n const margin = loader.getConfigValue<number>(\r\n 'DL_ACCESS_REFRESH_MARGIN_SEC',\r\n { defaultValue: 300 },\r\n );\r\n const remaining = exp - now;\r\n\r\n if (remaining <= margin)\r\n return {\r\n ok: true,\r\n reason: `within_margin remaining=${remaining}s margin=${margin}s`,\r\n };\r\n return {\r\n ok: false,\r\n reason: `too_early remaining=${remaining}s margin=${margin}s`,\r\n };\r\n }\r\n\r\n // --- token persistence ---\r\n private ensureAccessExpPersisted(\r\n ctx: OrchestratorContext,\r\n reason: TokenReason,\r\n ) {\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const access = this.accessToken;\r\n const curExp = cfg.tokens?.accessTokenExpSec;\r\n\r\n if (!access) return;\r\n if (typeof curExp === 'number' && Number.isFinite(curExp)) return;\r\n\r\n const exp = this.tryDecodeExp(access);\r\n if (!exp) return;\r\n\r\n const updated: Configuration = {\r\n ...cfg,\r\n tokens: { ...(cfg.tokens ?? {}), accessTokenExpSec: exp },\r\n };\r\n\r\n ctx.engine.applyConfiguration(updated);\r\n ctx.bus.emit('config:save:requested', updated);\r\n\r\n ctx.notifier.info(\r\n `Auth: derived accessTokenExpSec=${exp} (${reason})`,\r\n { scope: NotifyScope.System },\r\n );\r\n }\r\n\r\n private persistTokens(\r\n ctx: OrchestratorContext,\r\n accessToken: string,\r\n expiresInSec?: number,\r\n ) {\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n\r\n const expFromJwt = this.tryDecodeExp(accessToken);\r\n const expFallback =\r\n typeof expiresInSec === 'number' && Number.isFinite(expiresInSec)\r\n ? Math.floor(Date.now() / 1000) + expiresInSec\r\n : undefined;\r\n\r\n const updated: Configuration = {\r\n ...cfg,\r\n tokens: {\r\n ...(cfg.tokens ?? {}),\r\n accessTokenExpSec: expFromJwt ?? expFallback,\r\n },\r\n };\r\n\r\n ctx.engine.applyConfiguration(updated);\r\n ctx.bus.emit('config:save:requested', updated);\r\n\r\n ctx.notifier.info(\r\n `Auth: tokens updated exp=${updated.tokens?.accessTokenExpSec ?? '-'}`,\r\n { scope: NotifyScope.System },\r\n );\r\n }\r\n\r\n private async teardownTokens(ctx: OrchestratorContext, why: string) {\r\n this.accessToken = undefined;\r\n const cfg = ctx.engine.configurationContext.configuration;\r\n const updated: Configuration = { ...cfg, tokens: undefined };\r\n\r\n ctx.engine.applyConfiguration(updated);\r\n ctx.bus.emit('config:save:requested', updated);\r\n\r\n this.clearTimers();\r\n this.resetConnectionState();\r\n\r\n ctx.bus.emit('auth:signout:requested', void 0);\r\n ctx.notifier.warn(\r\n `Auth: signed out (${why}). Please run signin.`,\r\n );\r\n }\r\n\r\n // --- helpers ---\r\n private tryDecodeExp(jwt: string): number | null {\r\n try {\r\n const payload = decodeJwt(jwt);\r\n return typeof payload.exp === 'number' ? payload.exp : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private send(ctx: OrchestratorContext, msg: unknown) {\r\n ctx.bus.emit('ws:tx', { text: JSON.stringify(msg) });\r\n }\r\n\r\n private resetConnectionState() {\r\n this.connectionId = null;\r\n this.sessionId = null;\r\n this.phase = 'IDLE';\r\n }\r\n\r\n private clearTimers() {\r\n if (this.refreshScheduler) {\r\n this.refreshScheduler.stop();\r\n this.refreshScheduler = null;\r\n }\r\n if (this.refreshRetryScheduler) {\r\n this.refreshRetryScheduler.stop();\r\n this.refreshRetryScheduler = null;\r\n }\r\n if (this.conflictTimer) clearTimeout(this.conflictTimer);\r\n\r\n this.conflictTimer = null;\r\n this.pendingConflictRequest = null;\r\n }\r\n}\r\n", "// agent/src/protocol/messages.ts\r\nimport { z } from \"zod\";\r\n\r\n/**\r\n * Shared defs\r\n */\r\nexport const ToolDef = z.object({\r\n name: z.string().min(1),\r\n description: z.string().optional(),\r\n inputSchema: z.any().optional(),\r\n outputSchema: z.any().optional(),\r\n defaults: z.record(z.string(), z.unknown()).optional(),\r\n version: z.string().optional(),\r\n errorCodes: z.array(z.string()).optional(),\r\n});\r\nexport type ToolDef = z.infer<typeof ToolDef>;\r\n\r\nexport const DirectoryDef = z.object({\r\n id: z.string().min(1),\r\n name: z.string().min(1),\r\n path: z.string().optional(),\r\n path_hint: z.string().optional(),\r\n policy: z.any().optional(),\r\n});\r\nexport type DirectoryDef = z.infer<typeof DirectoryDef>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * connect\r\n */\r\nexport const ConnectRequestSchema = z\r\n .object({\r\n type: z.literal(\"connect\"),\r\n device_id: z.string().min(1),\r\n\r\n agent_version: z.string().min(1),\r\n platform: z.string().optional(),\r\n hostname: z.string().optional(),\r\n device_tag: z.string().optional(),\r\n\r\n // PoP signature (required)\r\n ts: z.number(), // ms epoch\r\n nonce: z.string().min(8),\r\n sig: z.string().min(16), // base64\r\n\r\n // auth tokens (optional at connect)\r\n access_token: z.string().optional(),\r\n refresh_token: z.string().min(20).optional(),\r\n\r\n // optional: bootstrap key if server doesn't have it yet\r\n public_key_pem: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ConnectRequest = z.infer<typeof ConnectRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * connect_ack\r\n */\r\nconst ConnectAckOkSchema = z\r\n .object({\r\n type: z.literal(\"connect_ack\"),\r\n ok: z.literal(true),\r\n session_id: z.string().min(1),\r\n device_id: z.string().min(1),\r\n server_time: z.number(),\r\n\r\n auth: z.object({\r\n device_proof: z.literal(\"ok\"),\r\n access_token: z.enum([\"ok\", \"expired\", \"invalid\", \"missing\"]),\r\n }),\r\n\r\n // client should do next\r\n next: z.array(z.enum([\"refresh_access_token\", \"session_init\"])).min(1),\r\n\r\n // optional hint\r\n workspace_id: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ConnectAckOk = z.infer<typeof ConnectAckOkSchema>;\r\n\r\nconst ConnectAckErrSchema = z\r\n .object({\r\n type: z.literal(\"connect_ack\"),\r\n ok: z.literal(false),\r\n session_id: z.string().optional(),\r\n server_time: z.number(),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\nexport type ConnectAckErr = z.infer<typeof ConnectAckErrSchema>;\r\n\r\nexport const ConnectAckSchema = z.union([ConnectAckOkSchema, ConnectAckErrSchema]);\r\nexport type ConnectAck = z.infer<typeof ConnectAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * refresh_access_token\r\n */\r\nexport const RefreshAccessTokenRequestSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token\"),\r\n device_id: z.string().min(1),\r\n\r\n ts: z.number(), // ms epoch\r\n nonce: z.string().min(8),\r\n\r\n refresh_token: z.string().min(20),\r\n sig: z.string().min(16), // base64 signature over device_id|ts|nonce|sha256(refresh_token)\r\n\r\n session_id: z.string().min(1).optional(),\r\n })\r\n .strict();\r\nexport type RefreshAccessTokenRequest = z.infer<typeof RefreshAccessTokenRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * refresh_access_token_ack\r\n */\r\nconst RefreshAckOkSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token_ack\"),\r\n ok: z.literal(true),\r\n access_token: z.string().min(1),\r\n refresh_token: z.string().min(20), // rotated\r\n expires_in_sec: z.number().int().positive().optional(),\r\n next: z.array(z.literal(\"session_init\")).default([\"session_init\"]),\r\n })\r\n .strict();\r\n\r\nconst RefreshAckErrSchema = z\r\n .object({\r\n type: z.literal(\"refresh_access_token_ack\"),\r\n ok: z.literal(false),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const RefreshAccessTokenAckSchema = z.union([RefreshAckOkSchema, RefreshAckErrSchema]);\r\nexport type RefreshAccessTokenAck = z.infer<typeof RefreshAccessTokenAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * session_init\r\n */\r\nexport const SessionInitRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_init\"),\r\n device_id: z.string().min(1),\r\n session_id: z.string().min(1),\r\n })\r\n .strict();\r\nexport type SessionInitRequest = z.infer<typeof SessionInitRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_init_ack\r\n */\r\nconst SessionInitAckOkSchema = z\r\n .object({\r\n type: z.literal(\"session_init_ack\"),\r\n ok: z.literal(true),\r\n device_id: z.string().min(1),\r\n session_id: z.string().min(1),\r\n mode: z.enum([\"ACTIVE\", \"ACTIVE_RECLAIMED\", \"STANDBY\"]),\r\n reason: z.string().optional(),\r\n server_time: z.number(),\r\n\r\n next: z.array(z.enum([\"tools_publish\", \"directories_publish\"])).optional(),\r\n })\r\n .strict();\r\n\r\nconst SessionInitAckErrSchema = z\r\n .object({\r\n type: z.literal(\"session_init_ack\"),\r\n ok: z.literal(false),\r\n device_id: z.string().min(1),\r\n server_time: z.number(),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const SessionInitAckSchema = z.union([SessionInitAckOkSchema, SessionInitAckErrSchema]);\r\nexport type SessionInitAck = z.infer<typeof SessionInitAckSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_conflict (server prompts new connection)\r\n */\r\nexport const SessionConflictRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict\"),\r\n device_id: z.string().min(1),\r\n new_session_id: z.string().min(1),\r\n\r\n max_sessions: z.number().int().positive(),\r\n active_count: z.number().int().nonnegative(),\r\n\r\n deadline_ms: z.number().int().positive(),\r\n message: z.string().min(1),\r\n\r\n choices: z\r\n .array(\r\n z.object({\r\n id: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n default: z.boolean().optional(),\r\n prompt: z.string().optional(),\r\n })\r\n )\r\n .min(1),\r\n })\r\n .strict();\r\nexport type SessionConflictRequest = z.infer<typeof SessionConflictRequestSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * session_conflict_resolve\r\n */\r\nexport const SessionConflictResolveRequestSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve\"),\r\n device_id: z.string().min(1),\r\n new_session_id: z.string().min(1),\r\n choice: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n })\r\n .strict();\r\nexport type SessionConflictResolveRequest = z.infer<typeof SessionConflictResolveRequestSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * session_conflict_resolve_ack\r\n */\r\nconst SessionConflictResolveAckOkSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve_ack\"),\r\n ok: z.literal(true),\r\n device_id: z.string().min(1),\r\n choice: z.enum([\"USE_NEW\", \"KEEP_OLD\"]),\r\n next: z.array(z.enum([\"session_init\"])).optional(),\r\n })\r\n .strict();\r\n\r\nconst SessionConflictResolveAckErrSchema = z\r\n .object({\r\n type: z.literal(\"session_conflict_resolve_ack\"),\r\n ok: z.literal(false),\r\n device_id: z.string().min(1),\r\n error: z.object({\r\n code: z.string().min(1),\r\n message: z.string().min(1),\r\n }),\r\n })\r\n .strict();\r\n\r\nexport const SessionConflictResolveAckSchema = z.union([\r\n SessionConflictResolveAckOkSchema,\r\n SessionConflictResolveAckErrSchema,\r\n]);\r\nexport type SessionConflictResolveAck = z.infer<typeof SessionConflictResolveAckSchema>;\r\n\r\nexport const QuiesceRequestSchema = z.object({\r\n type: z.literal(\"quiesce\"),\r\n session_id: z.string().min(1),\r\n reason: z.enum([\"SESSION_REPLACED\"]),\r\n deadline_ms: z.number().int().positive(),\r\n}).strict();\r\n\r\nexport type QuiesceRequest = z.infer<typeof QuiesceRequestSchema>;\r\n\r\nexport const QuiesceAckSchema = z.object({\r\n type: z.literal(\"quiesce_ack\"),\r\n session_id: z.string().min(1),\r\n status: z.enum([\"IDLE\", \"BUSY\"]),\r\n}).strict();\r\n\r\nexport type QuiesceAck = z.infer<typeof QuiesceAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * tools_publish (+ ack)\r\n */\r\nexport const ToolsPublishRequestSchema = z\r\n .object({\r\n type: z.literal(\"tools_publish\"),\r\n device_id: z.string().min(1),\r\n workspace_id: z.string().optional(),\r\n tools: z.array(ToolDef).default([]),\r\n tools_version: z.string().optional(),\r\n })\r\n .strict();\r\nexport type ToolsPublishRequest = z.infer<typeof ToolsPublishRequestSchema>;\r\n\r\nexport const ToolsPublishAckSchema = z\r\n .object({\r\n type: z.literal(\"tools_publish_ack\"),\r\n ok: z.boolean(),\r\n device_id: z.string().min(1),\r\n tools_version: z.string().optional(),\r\n error: z.object({ code: z.string().min(1), message: z.string().min(1) }).optional(),\r\n })\r\n .strict();\r\nexport type ToolsPublishAck = z.infer<typeof ToolsPublishAckSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * directories_publish (+ ack)\r\n */\r\nexport const DirectoriesPublishRequestSchema = z\r\n .object({\r\n type: z.literal(\"directories_publish\"),\r\n device_id: z.string().min(1),\r\n workspace_id: z.string().optional(),\r\n directories: z.array(DirectoryDef).default([]),\r\n })\r\n .strict();\r\nexport type DirectoriesPublishRequest = z.infer<typeof DirectoriesPublishRequestSchema>;\r\n\r\nexport const DirectoriesPublishAckSchema = z\r\n .object({\r\n type: z.literal(\"directories_publish_ack\"),\r\n ok: z.boolean(),\r\n device_id: z.string().min(1),\r\n error: z.object({ code: z.string().min(1), message: z.string().min(1) }).optional(),\r\n })\r\n .strict();\r\nexport type DirectoriesPublishAck = z.infer<typeof DirectoriesPublishAckSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * tool_call (agent executes and replies tool_result)\r\n */\r\nexport const ToolCallRequestSchema = z\r\n .object({\r\n type: z.literal(\"tool_call\"),\r\n job_id: z.string().min(1),\r\n\r\n device_id: z.string().min(1).optional(),\r\n workspace_id: z.string().optional(),\r\n\r\n tool: z.string().min(1),\r\n args: z.record(z.string(), z.unknown()).default({}),\r\n })\r\n .strict();\r\nexport type ToolCallRequest = z.infer<typeof ToolCallRequestSchema>;\r\n\r\n/**\r\n * Agent -> Bridge\r\n * tool_result\r\n */\r\nexport const ToolMessage = z.object({\r\n type: z.enum([\"error\", \"warning\", \"info\"]),\r\n description: z.string().min(1),\r\n});\r\nexport type ToolMessage = z.infer<typeof ToolMessage>;\r\n\r\nexport const ToolResultResponseSchema = z\r\n .object({\r\n type: z.literal(\"tool_result\"),\r\n job_id: z.string().min(1),\r\n tool: z.string().min(1),\r\n\r\n ok: z.boolean(),\r\n result: z.unknown().optional(),\r\n error: z.unknown().optional(),\r\n\r\n messages: z.array(ToolMessage).optional(),\r\n timing: z\r\n .object({\r\n execution_ms: z.number(),\r\n execution_sec: z.number(),\r\n })\r\n .optional(),\r\n })\r\n .strict()\r\n .superRefine((data, ctx) => {\r\n if (data.ok && data.result === undefined) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: \"tool_result ok=true should include result\",\r\n path: [\"result\"],\r\n });\r\n }\r\n if (!data.ok && data.error === undefined) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: \"tool_result ok=false should include error\",\r\n path: [\"error\"],\r\n });\r\n }\r\n });\r\nexport type ToolResultResponse = z.infer<typeof ToolResultResponseSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * disconnect_notice (server hint before close)\r\n */\r\nexport const DisconnectNoticeResponseSchema = z\r\n .object({\r\n type: z.literal(\"disconnect_notice\"),\r\n code: z.number().int(),\r\n reason: z.string(),\r\n at: z.number(), // server time ms\r\n })\r\n .strict();\r\nexport type DisconnectNoticeResponse = z.infer<typeof DisconnectNoticeResponseSchema>;\r\n\r\n/**\r\n * Bridge -> Agent\r\n * promoted_active / demoted_standby (slot changes)\r\n * (Keep these if your server uses them; otherwise remove.)\r\n */\r\nexport const PromotedActiveResponseSchema = z\r\n .object({\r\n type: z.literal(\"promoted_active\"),\r\n workspaceId: z.string().min(1),\r\n })\r\n .strict();\r\nexport type PromotedActiveResponse = z.infer<typeof PromotedActiveResponseSchema>;\r\n\r\nexport const DemotedStandbyResponseSchema = z\r\n .object({\r\n type: z.literal(\"demoted_standby\"),\r\n workspaceId: z.string().min(1),\r\n })\r\n .strict();\r\nexport type DemotedStandbyResponse = z.infer<typeof DemotedStandbyResponseSchema>;\r\n\r\n/**\r\n * Union types\r\n *\r\n * AgentOutbound = what agent sends to bridge\r\n * BridgeOutbound = what bridge sends to agent\r\n */\r\nexport const BridgeInboundMsgSchema = z.union([\r\n ConnectRequestSchema,\r\n RefreshAccessTokenRequestSchema,\r\n SessionInitRequestSchema,\r\n SessionConflictResolveRequestSchema,\r\n ToolsPublishRequestSchema,\r\n DirectoriesPublishRequestSchema,\r\n ToolCallRequestSchema,\r\n ToolResultResponseSchema,\r\n QuiesceAckSchema,\r\n DisconnectNoticeResponseSchema,\r\n PromotedActiveResponseSchema,\r\n DemotedStandbyResponseSchema,\r\n]);\r\nexport type BridgeInboundMsg = z.infer<typeof BridgeInboundMsgSchema>;\r\n\r\nexport const BridgeOutboundMsgSchema = z.union([\r\n ConnectAckSchema,\r\n RefreshAccessTokenAckSchema,\r\n SessionInitAckSchema,\r\n SessionConflictRequestSchema,\r\n SessionConflictResolveAckSchema,\r\n ToolsPublishAckSchema,\r\n DirectoriesPublishAckSchema,\r\n ToolCallRequestSchema, \r\n QuiesceRequestSchema,\r\n DisconnectNoticeResponseSchema,\r\n PromotedActiveResponseSchema,\r\n DemotedStandbyResponseSchema,\r\n]);\r\nexport type BridgeOutboundMsg = z.infer<typeof BridgeOutboundMsgSchema>;\r\n", "import { z } from \"zod\";\r\n\r\n// ---- Start ----\r\nexport const DeviceAuthStartRequestSchema = z.object({\r\n device_id: z.string().optional(),\r\n device_name: z.string().optional(),\r\n platform: z.string().optional(),\r\n public_key_pem: z.string().min(1),\r\n});\r\nexport type DeviceAuthStartRequest = z.infer<typeof DeviceAuthStartRequestSchema>;\r\n\r\nexport const DeviceAuthStartResponseSchema = z.object({\r\n device_code: z.string(),\r\n user_code: z.string(),\r\n verification_uri: z.string(),\r\n verification_uri_complete: z.string(),\r\n expires_in: z.number(),\r\n interval: z.number(),\r\n challenge_id: z.string(),\r\n challenge: z.string(), // base64url\r\n});\r\nexport type DeviceAuthStartResponse = z.infer<typeof DeviceAuthStartResponseSchema>;\r\n\r\n// ---- Stream (STATUS ONLY) ----\r\n// What SSE returns in data: snapshots/errors only\r\nexport const DeviceAuthStreamResponseSchema = z.union([\r\n z.object({\r\n status: z.literal(\"pending\"),\r\n needs_proof: z.boolean(),\r\n }),\r\n z.object({\r\n status: z.literal(\"approved\"),\r\n needs_proof: z.boolean(),\r\n }),\r\n z.object({\r\n error: z.literal(\"access_denied\"),\r\n }),\r\n z.object({\r\n error: z.literal(\"expired_token\"),\r\n }),\r\n]);\r\n\r\nexport type DeviceAuthStreamRequest = {\r\n deviceCode: string;\r\n timeoutMs: number;\r\n signal?: AbortSignal;\r\n};\r\n\r\nexport type DeviceAuthStreamResponse = z.infer<typeof DeviceAuthStreamResponseSchema>;\r\n\r\n// ---- Prove ----\r\nexport const DeviceAuthProveRequestSchema = z.object({\r\n device_code: z.string(),\r\n challenge_id: z.string(),\r\n challenge: z.string(), \r\n signature_b64: z.string() \r\n});\r\nexport type DeviceAuthProveRequest = z.infer<typeof DeviceAuthProveRequestSchema>;\r\n\r\nexport const DeviceAuthProveResponseSchema = z.object({\r\n ok: z.literal(true),\r\n});\r\nexport type DeviceAuthProveResponse = z.infer<typeof DeviceAuthProveResponseSchema>;\r\n\r\n// ---- Token ----\r\nexport const DeviceAuthTokenRequestSchema = z.object({\r\n device_code: z.string(),\r\n});\r\nexport type DeviceAuthTokenRequest = z.infer<typeof DeviceAuthTokenRequestSchema>;\r\n\r\nexport const DeviceAuthTokenResponseSchema = z.object({\r\n access_token: z.string(),\r\n refresh_token: z.string(), \r\n token_type: z.literal(\"Bearer\"),\r\n expires_in: z.number(),\r\n device_id: z.string(),\r\n});\r\nexport type DeviceAuthTokenResponse = z.infer<typeof DeviceAuthTokenResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshRequestSchema = z.object({\r\n device_id: z.string().min(1),\r\n refresh_token: z.string().min(1),\r\n ts: z.number().int(),\r\n nonce: z.string().min(8),\r\n sig: z.string().min(16), // base64\r\n});\r\n\r\nexport type DeviceAuthRefreshRequest = z.infer<typeof DeviceAuthRefreshRequestSchema>;\r\n\r\nexport const DeviceAuthRefreshSuccessResponseSchema = z.object({\r\n ok: z.literal(true),\r\n access_token: z.string().min(10),\r\n refresh_token: z.string().min(10),\r\n expires_in_sec: z.number().int().positive(),\r\n device_id: z.string().min(1),\r\n});\r\nexport type DeviceAuthRefreshSuccessResponse = z.infer<typeof DeviceAuthRefreshSuccessResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshErrorResponseSchema = z.object({\r\n ok: z.literal(false),\r\n error: z.object({\r\n code: z.string(),\r\n message: z.string(),\r\n }),\r\n});\r\nexport type DeviceAuthRefreshErrorResponse = z.infer<typeof DeviceAuthRefreshErrorResponseSchema>;\r\n\r\nexport const DeviceAuthRefreshResponseSchema = z.union([DeviceAuthRefreshSuccessResponseSchema, DeviceAuthRefreshErrorResponseSchema]);\r\n\r\nexport type DeviceAuthRefreshResponse = z.infer<typeof DeviceAuthRefreshResponseSchema>;\r\n", "/**\n * Base types for all filesystem tools\n * Following SOLID and DRY principles - all shared types are defined here\n */\n\n// ============================================================================\n// Base Args Types\n// ============================================================================\n\n/**\n * Base arguments that all filesystem tools share\n */\nexport type BaseFsArgs = {\n directory_id: string;\n workspace_id?: string;\n device_id?: string;\n};\n\n/**\n * Base arguments for tools that operate on a specific path\n */\nexport type BaseFsPathArgs = BaseFsArgs & {\n path: string;\n};\n\n/**\n * Base arguments for tools that optionally operate on a path\n */\nexport type BaseFsOptionalPathArgs = BaseFsArgs & {\n path?: string;\n};\n\n/**\n * Common filtering options\n */\nexport type FsFilterOptions = {\n only?: 'all' | 'files' | 'dirs';\n include_hidden?: boolean;\n};\n\n/**\n * Common pagination options\n */\nexport type FsPaginationOptions = {\n limit?: number;\n offset?: number;\n};\n\n/**\n * Common sorting options\n */\nexport type FsSortOptions = {\n sort?: 'name' | 'mtime' | 'size';\n order?: 'asc' | 'desc';\n};\n\n/**\n * Common detail level options\n */\nexport type FsDetailOptions = {\n detail?: 'basic' | 'stat' | 'digest';\n};\n\n// ============================================================================\n// Common Output Types\n// ============================================================================\n\n/**\n * Standard entry shape for all filesystem list/tree/search operations\n */\nexport type FsEntry = {\n name: string;\n path: string; // relative to root\n type: 'file' | 'dir' | 'symlink' | 'other';\n size?: number; // file only\n mtime?: number; // epoch seconds\n ext?: string; // optional helper (file extension)\n hidden?: boolean; // if included\n ignored?: boolean; // normally filtered, but helpful for debug\n};\n\n/**\n * Standard pagination metadata\n */\nexport type PaginationMeta = {\n count: number; // items in this response\n limit: number; // max items requested\n offset: number; // offset used\n has_more: boolean; // whether more items exist\n next_offset?: number; // next offset to use (if has_more)\n};\n\n/**\n * Standard context metadata for filesystem operations\n */\nexport type FsContext = {\n workspace_id?: string;\n device_id?: string;\n directory_id: string;\n path: string; // relative path within directory\n};\n\n/**\n * Standard filtered metadata (for ignore system)\n */\nexport type FilteredMeta = {\n ignored_count: number; // number of entries filtered by ignore rules\n rules_count?: number; // number of ignore rules applied (for debug)\n};\n\n/**\n * Standard summary statistics for directory listings\n */\nexport type FsSummary = {\n total_entries: number;\n files: number;\n dirs: number;\n symlinks: number;\n hidden: number;\n ignored: number;\n by_ext?: Array<{ ext: string; count: number }>; // top N extensions\n total_file_bytes?: number; // only if detail=\"stat\" or \"digest\"\n};\n\n// ============================================================================\n// Tool Result Envelope\n// ============================================================================\n\n/**\n * Standard error shape for tool results\n */\nexport type ToolError = {\n code: string; // error code (e.g., \"PATH_ESCAPE\", \"NOT_FOUND\", \"PERMISSION_DENIED\")\n message: string; // human-readable message\n details?: Record<string, unknown>; // optional additional context\n};\n\n/**\n * Standard result envelope - success case\n */\nexport type ToolOk<T> = {\n ok: true;\n data: T;\n};\n\n/**\n * Standard result envelope - failure case\n */\nexport type ToolFail = {\n ok: false;\n error: ToolError;\n};\n\n/**\n * Standard result envelope - union type\n */\nexport type ToolResult<T> = ToolOk<T> | ToolFail;\n\n/**\n * Helper to create success result\n */\nexport function ok<T>(data: T): ToolOk<T> {\n return { ok: true, data };\n}\n\n/**\n * Helper to create failure result\n */\nexport function fail(error: ToolError): ToolFail {\n return { ok: false, error };\n}\n", "type StepCallback = (stepSec: number, remainingSec: number) => void;\r\ntype TaskCallback = () => void;\r\n\r\nexport class Scheduler {\r\n private timeout: NodeJS.Timeout | null = null;\r\n private interval: NodeJS.Timeout | null = null;\r\n private totalSec = 0;\r\n private remainingSec = 0;\r\n private stepSec = 1;\r\n private task: TaskCallback | null = null;\r\n private stepCb: StepCallback | null = null;\r\n\r\n /** set interval between steps (default 1s) */\r\n public setStep(sec: number): this {\r\n this.stepSec = Math.max(1, sec);\r\n return this;\r\n }\r\n\r\n /** schedule the main task to run after delaySec seconds */\r\n public schedule(task: TaskCallback, delaySec: number): this {\r\n this.task = task;\r\n this.totalSec = delaySec;\r\n this.remainingSec = delaySec;\r\n return this;\r\n }\r\n\r\n /** callback called every step */\r\n public onStep(cb: StepCallback): this {\r\n this.stepCb = cb;\r\n return this;\r\n }\r\n\r\n /** start counting down */\r\n public start(): this {\r\n this.clear();\r\n\r\n if (this.remainingSec <= 0) {\r\n this.runTask();\r\n return this;\r\n }\r\n\r\n // call step callback immediately\r\n this.stepCb?.(this.stepSec, this.remainingSec);\r\n\r\n this.interval = setInterval(() => {\r\n this.remainingSec -= this.stepSec;\r\n if (this.remainingSec <= 0) {\r\n this.runTask();\r\n } else {\r\n this.stepCb?.(this.stepSec, this.remainingSec);\r\n }\r\n }, this.stepSec * 1000);\r\n\r\n return this;\r\n }\r\n\r\n /** stop/cancel the timer */\r\n public stop(): this {\r\n this.clear();\r\n return this;\r\n }\r\n\r\n /** reset and start over */\r\n public restart(): this {\r\n this.remainingSec = this.totalSec;\r\n return this.start();\r\n }\r\n\r\n /** internal task runner */\r\n private runTask() {\r\n this.clear();\r\n if (this.task) {\r\n try {\r\n this.task();\r\n } catch (err) {\r\n throw new Error(`Scheduler task failed: ${err}`);\r\n }\r\n }\r\n }\r\n\r\n /** clear all timers */\r\n private clear() {\r\n if (this.timeout) {\r\n clearTimeout(this.timeout);\r\n this.timeout = null;\r\n }\r\n if (this.interval) {\r\n clearInterval(this.interval);\r\n this.interval = null;\r\n }\r\n }\r\n}\r\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsListOutput, FsListArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\ntype FsEntry = {\n name: string;\n path: string;\n type: 'file' | 'dir' | 'symlink' | 'other';\n size?: number;\n mtime?: number;\n ext?: string;\n hidden?: boolean;\n ignored?: boolean;\n};\n\nfunction sortEntries(entries: FsEntry[], sort: 'name' | 'mtime' | 'size', order: 'asc' | 'desc'): FsEntry[] {\n const sorted = [...entries];\n const multiplier = order === 'asc' ? 1 : -1;\n\n sorted.sort((a, b) => {\n if (sort === 'name') {\n return multiplier * a.name.localeCompare(b.name);\n }\n if (sort === 'mtime') {\n const aTime = a.mtime ?? 0;\n const bTime = b.mtime ?? 0;\n return multiplier * (aTime - bTime);\n }\n if (sort === 'size') {\n const aSize = a.size ?? 0;\n const bSize = b.size ?? 0;\n return multiplier * (aSize - bSize);\n }\n return 0;\n });\n\n return sorted;\n}\n\nfunction filterEntries(entries: FsEntry[], only: 'all' | 'files' | 'dirs'): FsEntry[] {\n if (only === 'all') return entries;\n if (only === 'files') {\n return entries.filter((e) => e.type === 'file' || e.type === 'symlink');\n }\n if (only === 'dirs') {\n return entries.filter((e) => e.type === 'dir');\n }\n return entries;\n}\n\n/**\n * Executer for fs_list tool\n */\nexport class FsListExecuter extends BaseExecuter<FsListArgs, FsListOutput> {\n protected async executeTool(args: FsListArgs): Promise<FsListOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path);\n\n const limit = Math.min(Math.max(args.limit ?? 200, 1), 1000);\n const offset = Math.max(args.offset ?? 0, 0);\n const includeHidden = args.include_hidden ?? false;\n const only = args.only ?? 'all';\n const sort = args.sort ?? 'name';\n const order = args.order ?? 'asc';\n const detail = args.detail ?? 'stat';\n\n // Check that target is a directory\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('list', context, false, 'Path is not a directory.');\n throw toolErr('NOT_A_DIRECTORY', 'Path is not a directory.', {\n path: rel,\n hint: 'The path must point to a directory, not a file. Use fs_read to read files, or provide a directory path for listing.',\n });\n }\n } catch (e: any) {\n // If it's already a ToolError, rethrow\n if (e?.code && e?.message && typeof e?.code === 'string') {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('list', context, false, e.message);\n throw e;\n }\n throw mapFsError(e, 'Failed to list directory.');\n }\n\n // Read directory entries\n let dirents;\n try {\n dirents = await fs.readdir(absTarget, { withFileTypes: true });\n } catch (e) {\n throw mapFsError(e, 'Failed to read directory.');\n }\n\n // Filter hidden unless include_hidden\n let visibleDirents = includeHidden ? dirents : dirents.filter((d) => !d.name.startsWith('.'));\n\n // Build entries with metadata and apply ignore system\n const allEntries: FsEntry[] = [];\n let ignoredCount = 0;\n const summary: FsListOutput['summary'] = {\n total_entries: 0,\n files: 0,\n dirs: 0,\n symlinks: 0,\n hidden: 0,\n ignored: 0,\n total_file_bytes: 0,\n };\n const extCounts = new Map<string, number>();\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n for (const d of visibleDirents) {\n const full = path.join(absTarget, d.name);\n const rawRelPath = rel === '.' ? d.name : path.posix.join(rel, d.name);\n // Normalize to POSIX separators so ignore rules see proper segments\n const entryRelPath = rawRelPath.replace(/\\\\/g, '/');\n\n let type: FsEntry['type'] = 'other';\n if (d.isDirectory()) type = 'dir';\n else if (d.isFile()) type = 'file';\n else if (d.isSymbolicLink()) type = 'symlink';\n\n const isHidden = d.name.startsWith('.');\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, d.isDirectory(), ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n ignoredCount++;\n summary!.ignored++;\n continue; // always filter ignored entries\n }\n\n // Update summary counts\n summary!.total_entries++;\n if (type === 'file') summary!.files++;\n else if (type === 'dir') summary!.dirs++;\n else if (type === 'symlink') summary!.symlinks++;\n if (isHidden) summary!.hidden++;\n\n // Get stat for size/mtime (only if detail requires it)\n let size: number | undefined;\n let mtime: number | undefined;\n if (detail === 'stat' || detail === 'digest') {\n try {\n const st = await fs.stat(full);\n if (st.isFile()) {\n size = st.size;\n summary!.total_file_bytes = (summary!.total_file_bytes ?? 0) + st.size;\n }\n mtime = Math.floor(st.mtimeMs / 1000);\n } catch {\n // Stat failed, continue without size/mtime\n }\n }\n\n // Extract extension and count\n const ext = type === 'file' ? path.extname(d.name).slice(1) : undefined;\n if (ext && (detail === 'stat' || detail === 'digest')) {\n extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n allEntries.push({\n name: d.name,\n path: entryRelPath,\n type,\n size,\n mtime,\n ext,\n hidden: isHidden,\n ignored: false, // already filtered out ignored entries\n });\n }\n\n // Build top extensions list for summary (top 10)\n if (detail === 'digest' && extCounts.size > 0) {\n summary!.by_ext = Array.from(extCounts.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n }\n\n // Apply type filter (files/dirs)\n const filteredEntries = filterEntries(allEntries, only);\n\n // Apply sorting\n const sortedEntries = sortEntries(filteredEntries, sort, order);\n\n // Apply pagination\n const page = sortedEntries.slice(offset, offset + limit);\n const next_offset = offset + page.length;\n const has_more = next_offset < sortedEntries.length;\n\n const meta = {\n count: page.length,\n limit,\n offset,\n has_more,\n next_offset: has_more ? next_offset : undefined,\n };\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n const filtered = { ignored_count: ignoredCount };\n\n const result: FsListOutput = {\n items: page,\n meta,\n context,\n filtered,\n };\n\n // Include summary when detail=\"digest\"\n if (detail === 'digest') {\n result.summary = summary;\n }\n\n // Audit successful list operation\n auditFsOperation('list', context, true, undefined, {\n file_count: page.length,\n });\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_list tool\n */\nexport async function executeFsList(\n config: Configuration,\n args: FsListArgs\n): Promise<ToolResult<FsListOutput>> {\n const executer = new FsListExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\nimport { ok, fail } from '@devicelink-workspace/domain';\nimport type { ToolResult, ToolError } from '@devicelink-workspace/domain';\n\n/**\n * Base class for tool executers\n * Provides common functionality for all executers:\n * - Configuration access\n * - Error handling\n * - Result wrapping\n */\nexport abstract class BaseExecuter<TArgs, TOutput> {\n protected readonly config: Configuration;\n\n constructor(config: Configuration) {\n this.config = config;\n }\n\n /**\n * Execute the tool with the provided arguments\n * This is the main entry point that handles error handling and result wrapping\n */\n public async execute(args: TArgs): Promise<ToolResult<TOutput>> {\n try {\n const output = await this.executeTool(args);\n return ok(output);\n } catch (e: unknown) {\n if (this.isToolError(e)) {\n return fail(e);\n }\n // Don't leak internal error details (stack traces, OS paths) to MCP clients\n const safeMessage = e instanceof Error ? e.message : 'An unexpected error occurred';\n return fail({\n code: 'INTERNAL',\n message: safeMessage,\n });\n }\n }\n\n /**\n * Abstract method that subclasses must implement\n * This is where the actual tool function is called\n */\n protected abstract executeTool(args: TArgs): Promise<TOutput>;\n\n /**\n * Type guard to check if an error is a ToolError\n */\n protected isToolError(e: unknown): e is ToolError {\n return (\n typeof e === 'object' &&\n e !== null &&\n 'code' in e &&\n 'message' in e &&\n typeof (e as any).code === 'string' &&\n typeof (e as any).message === 'string'\n );\n }\n}\n", "import path from 'node:path';\r\nimport fs from 'node:fs';\r\nimport type { Configuration } from '../../../core/configuration.js';\r\n\r\n/**\r\n * Ignore rule types\r\n */\r\nexport type IgnoreRule = {\r\n pattern: string; // glob pattern or simple string\r\n type: 'glob' | 'exact' | 'prefix';\r\n};\r\n\r\n/**\r\n * Context for ignore checking\r\n */\r\nexport type IgnoreContext = {\r\n directory_id: string;\r\n workspace_id?: string;\r\n directory_path: string; // absolute path to directory\r\n};\r\n\r\n/**\r\n * Result of ignore check\r\n */\r\nexport type IgnoreResult = {\r\n shouldIgnore: boolean;\r\n matchedRule?: string; // which rule matched (for debug)\r\n reason?: string; // reason for ignoring (e.g., 'denylist:secrets')\r\n};\r\n\r\n/**\r\n * High-risk default denylist (security baseline)\r\n * This is evaluated BEFORE user-configurable ignore rules.\r\n * These patterns are always blocked regardless of user configuration.\r\n */\r\nfunction matchesDefaultDenylist(relPath: string): IgnoreResult | null {\r\n const normalized = relPath.replace(/\\\\/g, '/');\r\n \r\n // Prefix rules (match anywhere in path)\r\n if (normalized.includes('/secrets/') || normalized.startsWith('secrets/')) {\r\n return { shouldIgnore: true, reason: 'denylist:secrets', matchedRule: 'secrets/' };\r\n }\r\n if (normalized.includes('/.env') || normalized.startsWith('.env')) {\r\n return { shouldIgnore: true, reason: 'denylist:env', matchedRule: '.env' };\r\n }\r\n if (normalized.includes('/id_rsa') || normalized.endsWith('/id_rsa')) {\r\n return { shouldIgnore: true, reason: 'denylist:ssh', matchedRule: 'id_rsa' };\r\n }\r\n if (normalized.includes('/id_ed25519') || normalized.endsWith('/id_ed25519')) {\r\n return { shouldIgnore: true, reason: 'denylist:ssh', matchedRule: 'id_ed25519' };\r\n }\r\n \r\n // Suffix rules (file extensions)\r\n if (normalized.endsWith('.pem')) {\r\n return { shouldIgnore: true, reason: 'denylist:pem', matchedRule: '*.pem' };\r\n }\r\n if (normalized.endsWith('.key')) {\r\n return { shouldIgnore: true, reason: 'denylist:key', matchedRule: '*.key' };\r\n }\r\n if (normalized.endsWith('.p12')) {\r\n return { shouldIgnore: true, reason: 'denylist:p12', matchedRule: '*.p12' };\r\n }\r\n if (normalized.endsWith('.pfx')) {\r\n return { shouldIgnore: true, reason: 'denylist:pfx', matchedRule: '*.pfx' };\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/**\r\n * Default ignore patterns (applied to all directories)\r\n */\r\nconst DEFAULT_IGNORE_PATTERNS: IgnoreRule[] = [\r\n // Segment-exact directory/file names (match ANY path segment)\r\n { pattern: 'node_modules', type: 'exact' },\r\n { pattern: '.git', type: 'exact' },\r\n { pattern: 'dist', type: 'exact' },\r\n { pattern: 'build', type: 'exact' },\r\n { pattern: '.next', type: 'exact' },\r\n { pattern: '.cache', type: 'exact' },\r\n { pattern: '.DS_Store', type: 'exact' },\r\n { pattern: 'Thumbs.db', type: 'exact' },\r\n\r\n // True globs\r\n { pattern: '*.tmp', type: 'glob' },\r\n { pattern: '*.log', type: 'glob' },\r\n { pattern: '.env*', type: 'glob' },\r\n];\r\n\r\n/**\r\n * Load ignore rules for a directory\r\n *\r\n * Priority:\r\n * 1. Directory-specific ignore file (e.g., .devicelinkignore in directory)\r\n * 2. Workspace-level ignore rules (future: from config)\r\n * 3. Global default patterns\r\n */\r\nexport function loadIgnoreRules(cfg: Configuration, directory_id: string, workspace_id?: string): IgnoreRule[] {\r\n const directory = cfg.directories.find((r) => r.id === directory_id);\r\n if (!directory) {\r\n return DEFAULT_IGNORE_PATTERNS;\r\n }\r\n\r\n const rules: IgnoreRule[] = [];\r\n\r\n // Load directory-specific ignore file\r\n const ignoreFilePath = path.join(directory.path, '.devicelinkignore');\r\n if (fs.existsSync(ignoreFilePath)) {\r\n try {\r\n const content = fs.readFileSync(ignoreFilePath, 'utf-8');\r\n const lines = content\r\n .split('\\n')\r\n .map((line) => line.trim())\r\n .filter((line) => line && !line.startsWith('#'));\r\n\r\n for (const line of lines) {\r\n // Simple pattern detection\r\n if (line.includes('*') || line.includes('?')) {\r\n rules.push({ pattern: line, type: 'glob' });\r\n } else if (line.startsWith('/')) {\r\n // Prefix match\r\n rules.push({ pattern: line.slice(1), type: 'prefix' });\r\n } else {\r\n // Exact or simple match\r\n rules.push({ pattern: line, type: 'exact' });\r\n }\r\n }\r\n } catch (error) {\r\n // If we can't read the ignore file, continue with defaults\r\n console.warn(`[ignore] Failed to read .devicelinkignore: ${error}`);\r\n }\r\n }\r\n\r\n // Future: workspace-level ignore rules from config\r\n // if (workspace_id) { ... }\r\n\r\n // Add defaults last (lowest priority)\r\n rules.push(...DEFAULT_IGNORE_PATTERNS);\r\n\r\n return rules;\r\n}\r\n\r\n/**\r\n * Check if a path should be ignored\r\n *\r\n * @param relPath - Relative path from directory (e.g., \"src/index.ts\" or \"node_modules/package\")\r\n * @param isDir - Whether this is a directory\r\n * @param ctx - Ignore context\r\n * @returns IgnoreResult indicating if path should be ignored\r\n */\r\nexport function shouldIgnore(\r\n relPath: string,\r\n isDir: boolean,\r\n ctx: IgnoreContext,\r\n cfg: Configuration\r\n): IgnoreResult {\r\n // Security baseline denylist first (cannot be overridden)\r\n const denied = matchesDefaultDenylist(relPath);\r\n if (denied) {\r\n return denied;\r\n }\r\n\r\n const rules = loadIgnoreRules(cfg, ctx.directory_id, ctx.workspace_id);\r\n\r\n // Normalize path separators\r\n const normalizedPath = relPath.replace(/\\\\/g, '/');\r\n const pathParts = normalizedPath.split('/').filter(Boolean);\r\n\r\n for (const rule of rules) {\r\n let matched = false;\r\n\r\n if (rule.type === 'exact') {\r\n // Check if any path segment matches exactly\r\n matched = pathParts.some((part) => part === rule.pattern);\r\n } else if (rule.type === 'prefix') {\r\n // Check if path starts with prefix\r\n matched = normalizedPath.startsWith(rule.pattern);\r\n } else if (rule.type === 'glob') {\r\n // If pattern has no slash and no wildcard chars, treat it like segment-exact.\r\n if (!rule.pattern.includes('/') && !rule.pattern.includes('*') && !rule.pattern.includes('?')) {\r\n matched = pathParts.some((part) => part.toLowerCase() === rule.pattern.toLowerCase());\r\n } else {\r\n matched = matchesGlob(normalizedPath, rule.pattern, isDir);\r\n }\r\n }\r\n\r\n if (matched) {\r\n return { shouldIgnore: true, matchedRule: rule.pattern };\r\n }\r\n }\r\n\r\n return { shouldIgnore: false };\r\n}\r\n\r\n/**\r\n * Simple glob matcher\r\n * Supports: *, **, ? patterns\r\n */\r\nfunction matchesGlob(path: string, pattern: string, isDir: boolean): boolean {\r\n // Convert glob to regex\r\n let regexStr = '^';\r\n let i = 0;\r\n\r\n while (i < pattern.length) {\r\n const char = pattern[i];\r\n if (char === '*') {\r\n if (i + 1 < pattern.length && pattern[i + 1] === '*') {\r\n // ** matches any number of directories\r\n regexStr += '.*';\r\n i += 2;\r\n } else {\r\n // * matches any characters except path separator\r\n regexStr += '[^/]*';\r\n i++;\r\n }\r\n } else if (char === '?') {\r\n regexStr += '[^/]';\r\n i++;\r\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\r\n regexStr += '\\\\' + char;\r\n i++;\r\n } else {\r\n regexStr += char;\r\n i++;\r\n }\r\n }\r\n\r\n regexStr += '$';\r\n\r\n try {\r\n const regex = new RegExp(regexStr, 'i'); // case-insensitive\r\n return regex.test(path);\r\n } catch {\r\n // If regex is invalid, fall back to simple substring match\r\n return path.toLowerCase().includes(pattern.toLowerCase());\r\n }\r\n}\r\n\r\n/**\r\n * Count ignored entries (for filtered metadata)\r\n */\r\nexport function countIgnored(\r\n entries: Array<{ name: string; path?: string }>,\r\n isDir: (entry: { name: string }) => boolean,\r\n ctx: IgnoreContext,\r\n cfg: Configuration\r\n): number {\r\n let count = 0;\r\n for (const entry of entries) {\r\n const relPath = entry.path || entry.name;\r\n const result = shouldIgnore(relPath, isDir(entry), ctx, cfg);\r\n if (result.shouldIgnore) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n}\r\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { ToolError } from '@devicelink-workspace/domain';\n\n/**\n * Normalize a user-provided relative path into POSIX-style (forward slashes),\n * and reject obvious bad inputs early.\n */\nexport function normalizeRelPath(input: string): string {\n const raw = (input ?? '').trim();\n if (!raw) return '.';\n\n // Block null bytes\n if (raw.includes('\\0')) {\n throw toolErr('INVALID_INPUT', 'Path contains null byte.');\n }\n\n // Block absolute paths (POSIX)\n if (raw.startsWith('/')) {\n throw toolErr('PATH_ESCAPE', 'Absolute paths are not allowed. Use a path relative to the root.', {\n hint: 'Use relative paths like \"src/file.ts\" or \".\" for the root directory. Paths must be relative to the configured root.',\n });\n }\n\n // Block Windows absolute paths: C:\\ or C:/, \\\\server\\share\n if (/^[a-zA-Z]:[\\\\/]/.test(raw) || raw.startsWith('\\\\\\\\') || raw.startsWith('//')) {\n throw toolErr('PATH_ESCAPE', 'Absolute/drive/UNC paths are not allowed. Use a path relative to the root.', {\n hint: 'Use relative paths like \"src/file.ts\" or \".\" for the root directory. Do not use drive letters (C:) or UNC paths (\\\\\\\\server).',\n });\n }\n\n // Normalize slashes to POSIX\n const posixish = raw.replace(/\\\\/g, '/');\n\n // Normalize '.' and '..' segments safely\n const norm = path.posix.normalize(posixish);\n\n // Disallow escaping root via '..'\n // norm can be \"..\" or start with \"../\" if it escapes\n if (norm === '..' || norm.startsWith('../')) {\n throw toolErr('PATH_ESCAPE', 'Path escapes the root.', {\n hint: 'Paths cannot use \"..\" to escape the configured root directory. Use paths relative to the root, like \"src/file.ts\" or \"subdir/file.ts\".',\n });\n }\n\n // Disallow weird URL-ish schema tricks\n if (/^[a-zA-Z]+:\\/\\//.test(norm)) {\n throw toolErr('INVALID_INPUT', 'URL-style paths are not allowed.', {\n hint: 'Paths cannot use URL schemes (like \"http://\" or \"file://\"). Use simple relative paths like \"src/file.ts\".',\n });\n }\n\n return norm === '' ? '.' : norm;\n}\n\n/**\n * Resolve an input path safely inside a configured root path.\n * Returns absolute target + a normalized relative path (POSIX).\n *\n * IMPORTANT: uses realpath containment checks to prevent symlink/junction escapes.\n */\nexport async function resolveInRoot(\n rootPath: string,\n inputRel: string\n): Promise<{ absTarget: string; rel: string }> {\n const rel = normalizeRelPath(inputRel);\n\n // Resolve root first\n const absRoot = path.resolve(rootPath);\n const realRoot = await fs.realpath(absRoot);\n\n // Construct candidate under root (syntactic)\n const candidate = path.resolve(realRoot, rel === '.' ? '' : rel);\n\n // Quick containment check (syntactic)\n const relToRoot = path.relative(realRoot, candidate);\n if (relToRoot.startsWith('..') || path.isAbsolute(relToRoot)) {\n throw toolErr('PATH_ESCAPE', 'Path escapes the root.', {\n hint: 'The resolved path escapes the configured root directory. Ensure the path stays within the root boundaries.',\n });\n }\n\n // Symlink/junction protection (semantic)\n // If candidate exists, realpath resolves through symlinks/junctions.\n try {\n const realCandidate = await fs.realpath(candidate);\n const rel2 = path.relative(realRoot, realCandidate);\n if (rel2.startsWith('..') || path.isAbsolute(rel2)) {\n throw toolErr('PATH_ESCAPE', 'Symlink/junction escape detected.', {\n hint: 'A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries.',\n });\n }\n return { absTarget: realCandidate, rel };\n } catch (e: any) {\n // For non-existent targets, we can still be safe by resolving the nearest existing parent.\n if (e?.code !== 'ENOENT') throw e;\n\n const parts = rel.split('/').filter(Boolean);\n for (let i = parts.length; i > 0; i--) {\n const parentRel = parts.slice(0, i).join('/');\n const restRel = parts.slice(i).join('/');\n\n const parentCandidate = path.resolve(realRoot, parentRel);\n try {\n const realParent = await fs.realpath(parentCandidate);\n const relParent = path.relative(realRoot, realParent);\n if (relParent.startsWith('..') || path.isAbsolute(relParent)) {\n throw toolErr('PATH_ESCAPE', 'Symlink/junction escape detected.', {\n hint: 'A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries.',\n });\n }\n return { absTarget: restRel ? path.join(realParent, restRel) : realParent, rel };\n } catch (err: any) {\n if (err?.code === 'ENOENT') continue;\n throw err;\n }\n }\n\n // Nothing exists; treat as not found (and still safe)\n throw toolErr('NOT_FOUND', 'Path not found.', {\n hint: 'The specified path does not exist. Verify the path is correct and that the file or directory exists within the configured root.',\n });\n }\n}\n\n/**\n * Consistent context injection (always use normalized rel path).\n */\nexport function makeContext(args: {\n workspace_id?: string;\n device_id?: string;\n directory_id: string;\n path: string;\n}): { directory_id: string; workspace_id?: string; device_id?: string; path: string } {\n return {\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: args.directory_id,\n path: normalizeRelPath(args.path),\n };\n}\n\n/**\n * Map node fs errors to stable tool errors.\n */\nexport function mapFsError(e: any, fallbackMessage: string): ToolError {\n const code = String(e?.code ?? '');\n\n if (code === 'ENOENT') return toolError('NOT_FOUND', 'Path not found.', { fs_code: code });\n if (code === 'ENOTDIR') return toolError('NOT_A_DIRECTORY', 'Path is not a directory.', { fs_code: code });\n if (code === 'EISDIR') return toolError('NOT_A_FILE', 'Path is a directory, not a file.', { fs_code: code });\n if (code === 'EACCES' || code === 'EPERM')\n return toolError('PERMISSION_DENIED', 'Permission denied.', { fs_code: code });\n\n return toolError('INTERNAL', fallbackMessage, { fs_code: code });\n}\n\n/**\n * A tiny helper to throw ToolError as an exception (if you still use throws internally).\n * You can also return these instead once you convert handlers to ToolResult<> envelopes.\n */\nexport function toolErr(code: string, message: string, details?: Record<string, unknown>): ToolError {\n return toolError(code, message, details);\n}\n\nexport function toolError(code: string, message: string, details?: Record<string, unknown>): ToolError {\n return { code, message, details };\n}\n\n/**\n * Optional: validate directory_id quickly.\n * Tries to match by ID first, then falls back to single directory if available.\n * This handles cases where the directory_id from the resolver might not exactly match\n * the agent's configured directory ID (e.g., if agent was restarted with different directory config).\n */\nexport function requireDirectory(cfg: Configuration, directory_id: string) {\n if (Array.isArray(cfg.directories) && cfg.directories.length === 0) {\n throw toolErr('UNKNOWN_DIRECTORY', `No directories configured.`, {\n hint: `No directories configured. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,\n requested_directory_id: directory_id,\n available_directory_ids: cfg.directories.map(r => r.id),\n available_paths: cfg.directories.map(r => r.path),\n directory_count: cfg.directories.length,\n });\n }\n // First try exact ID match\n let directory = cfg.directories.find((r) => r.id === directory_id);\n \n // If not found and there's only one directory configured, use it as fallback\n // This handles the common case where the agent was restarted and the directory ID changed\n // but there's still only one directory configured\n if (!directory && cfg.directories.length === 1) {\n directory = cfg.directories[0];\n // Note: We don't log here because this function is called frequently and logging\n // should be done at a higher level if needed. The mismatch will be visible in errors.\n }\n \n if (!directory) {\n const availableIds = cfg.directories.map(r => r.id).join(', ') || 'none';\n const availablePaths = cfg.directories.map(r => r.path).join(', ') || 'none';\n const directoryIdStr = directory_id === undefined ? 'undefined (missing)' : String(directory_id);\n throw toolErr('UNKNOWN_DIRECTORY', `Unknown directory_id: ${directoryIdStr}`, {\n hint: `The directory_id \"${directoryIdStr}\" does not match any configured directory. Available directory IDs: ${availableIds}. Available paths: ${availablePaths}. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,\n requested_directory_id: directory_id,\n available_directory_ids: cfg.directories.map(r => r.id),\n available_paths: cfg.directories.map(r => r.path),\n directory_count: cfg.directories.length,\n });\n }\n return directory;\n}\n\n/**\n * Optional: type check helpers (avoid TOCTOU where possible)\n */\nexport async function statOrMap(absPath: string) {\n try {\n return await fs.stat(absPath);\n } catch (e) {\n throw mapFsError(e, 'Failed to stat path.');\n }\n}\n", "/**\n * Audit logging for filesystem operations\n * This can be extended later to integrate with the CLI logger system\n */\n\nexport type FsAuditOperation = 'read' | 'read_many' | 'list' | 'tree' | 'info' | 'grep' | 'search';\n\nexport type FsAuditEntry = {\n operation: FsAuditOperation;\n path: string; // relative path (sanitized)\n directory_id: string;\n workspace_id?: string;\n device_id?: string;\n success: boolean;\n error?: string;\n metadata?: {\n file_count?: number;\n match_count?: number;\n bytes_read?: number;\n };\n timestamp: number;\n};\n\n/**\n * Log filesystem operations for audit trail.\n * This provides security monitoring and compliance tracking.\n */\nexport function auditFsOperation(\n operation: FsAuditOperation,\n context: { directory_id: string; workspace_id?: string; device_id?: string; path: string },\n success: boolean,\n error?: string,\n metadata?: FsAuditEntry['metadata']\n): void {\n const entry: FsAuditEntry = {\n operation,\n path: context.path || '.',\n directory_id: context.directory_id,\n workspace_id: context.workspace_id,\n device_id: context.device_id,\n success,\n error: error ? error.substring(0, 200) : undefined, // Truncate long errors\n metadata,\n timestamp: Date.now(),\n };\n\n // Log as structured audit entry\n // TODO: Integrate with CLI logger system when available\n const logMsg = `[FS_AUDIT] ${operation} ${success ? 'SUCCESS' : 'FAILED'} directory=${entry.directory_id} path=${entry.path}${entry.workspace_id ? ` workspace=${entry.workspace_id}` : ''}${entry.device_id ? ` device=${entry.device_id}` : ''}${entry.error ? ` error=${entry.error}` : ''}${metadata ? ` ${JSON.stringify(metadata)}` : ''}`;\n \n // For now, audit operations are logged to console\n // This can be extended to use the CLI logger system\n // if (success) {\n // console.log(logMsg);\n // } else {\n // console.warn(logMsg);\n // }\n}\n", "import fs from 'node:fs/promises';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsReadOutput, FsReadArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { shouldIgnore } from '../util/ignore.js';\n\n/**\n * Executer for fs_read tool\n */\nexport class FsReadExecuter extends BaseExecuter<FsReadArgs, FsReadOutput> {\n protected async executeTool(args: FsReadArgs): Promise<FsReadOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget: absPath, rel } = await resolveInRoot(directory.path, args.path);\n\n // Check denylist and ignore rules\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n const ignoreResult = shouldIgnore(rel, false, ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`);\n throw toolErr('PERMISSION_DENIED', `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`, {\n path: rel,\n reason: ignoreResult.reason,\n });\n }\n\n const offset = Math.max(args.offset ?? 0, 0);\n const limit = Math.min(Math.max(args.limit ?? 40000, 1), 200000);\n const encoding = args.encoding ?? 'utf-8';\n\n // Check that target is a file\n let st;\n try {\n st = await fs.stat(absPath);\n } catch (e) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, mapFsError(e, 'Failed to stat file.').message);\n throw mapFsError(e, 'Failed to stat file.');\n }\n if (!st.isFile()) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, 'Path is not a file.');\n throw toolErr('NOT_A_FILE', 'Path is not a file.', {\n path: rel,\n hint: 'The path must point to a file, not a directory. Use fs_list or fs_tree to explore directories, or provide a file path to read.',\n });\n }\n\n let fh;\n try {\n fh = await fs.open(absPath, 'r');\n } catch (e) {\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, mapFsError(e, 'Failed to open file.').message);\n throw mapFsError(e, 'Failed to open file.');\n }\n\n try {\n const buf = Buffer.alloc(limit);\n const { bytesRead } = await fh.read(buf, 0, limit, offset);\n\n const slice = buf.subarray(0, bytesRead);\n const content = slice.toString(encoding as BufferEncoding);\n\n const next_offset = offset + bytesRead;\n const eof = bytesRead < limit;\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful read\n auditFsOperation('read', context, true, undefined, {\n bytes_read: bytesRead,\n });\n\n return {\n content,\n bytes_read: bytesRead,\n next_offset,\n eof,\n context,\n };\n } catch (e: any) {\n // Audit failed read\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n auditFsOperation('read', context, false, e?.message || String(e));\n throw e;\n } finally {\n await fh.close();\n }\n }\n}\n\n/**\n * Convenience function to execute fs_read tool\n */\nexport async function executeFsRead(\n config: Configuration,\n args: FsReadArgs\n): Promise<ToolResult<FsReadOutput>> {\n const executer = new FsReadExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsInfoOutput, FsInfoArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Executer for fs_info tool\n */\nexport class FsInfoExecuter extends BaseExecuter<FsInfoArgs, FsInfoOutput> {\n protected async executeTool(args: FsInfoArgs): Promise<FsInfoOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget: absPath, rel } = await resolveInRoot(directory.path, args.path);\n\n // Check if it's a symlink first\n let isSymlink = false;\n let target: string | undefined;\n\n try {\n target = await fs.readlink(absPath);\n isSymlink = true;\n } catch (e: any) {\n // Ignore if not a symlink; but if path missing, surface NOT_FOUND\n if (e?.code === 'ENOENT') throw mapFsError(e, 'Path not found.');\n }\n\n // Get stat information\n let stat;\n try {\n stat = isSymlink ? await fs.stat(absPath) : await fs.lstat(absPath);\n } catch (e) {\n throw mapFsError(e, 'Failed to stat path.');\n }\n\n // Determine type\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (stat.isDirectory()) {\n type = 'dir';\n } else if (stat.isFile()) {\n type = 'file';\n } else if (isSymlink) {\n type = 'symlink';\n }\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful info operation\n auditFsOperation('info', context, true);\n\n return {\n type,\n size: stat.isFile() ? stat.size : undefined,\n mtime: Math.floor(stat.mtimeMs / 1000),\n ctime: Math.floor(stat.ctimeMs / 1000),\n atime: Math.floor(stat.atimeMs / 1000),\n is_symlink: isSymlink,\n target: isSymlink ? target : undefined,\n context,\n };\n }\n}\n\n/**\n * Convenience function to execute fs_info tool\n */\nexport async function executeFsInfo(\n config: Configuration,\n args: FsInfoArgs\n): Promise<ToolResult<FsInfoOutput>> {\n const executer = new FsInfoExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport type { Dirent } from 'node:fs';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsTreeNode, FsTreeOutput, FsSummary, FsTreeDisplayRow, ToolError, FsTreeArgs } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { FsGrepExecuter, type FsGrepArgs } from './fs-grep.js';\nimport { FsReadManyExecuter, type FsReadManyArgs } from './fs-read-many.js';\n\nfunction collectFilePaths(node: FsTreeNode, out: string[], limit: number) {\n if (out.length >= limit) return;\n if (node.type === 'file') {\n out.push(node.path);\n return;\n }\n if (node.children) {\n for (const c of node.children) {\n if (out.length >= limit) break;\n collectFilePaths(c, out, limit);\n }\n }\n}\n\n/**\n * Deterministic ranking function that sorts files by importance buckets.\n * Returns paths sorted by: docs > config > ci > source > other\n */\nfunction rankImportant(paths: string[]): string[] {\n const getBucket = (p: string): number => {\n const x = p.toLowerCase();\n const parts = x.split('/');\n \n // Top priority: documentation files\n if (x === 'readme.md' || x.endsWith('/readme.md') || x.includes('/readme.md')) return 0;\n if (x.endsWith('.md')) return 1;\n \n // High priority: config files\n if (x.endsWith('package.json') || x.endsWith('pyproject.toml') || x.endsWith('go.mod') || \n x.endsWith('cargo.toml') || x.endsWith('pom.xml') || x.endsWith('build.gradle')) return 2;\n if (x.includes('dockerfile') || x.includes('compose') || x.endsWith('.env.example')) return 3;\n \n // Config directories\n if (parts.includes('config') || parts.includes('conf') || parts.includes('settings')) return 4;\n \n // CI/CD\n if (parts.includes('ci') || parts.includes('.github') || parts.includes('.gitlab') || \n parts.includes('jenkins') || x.includes('workflow')) return 5;\n \n // Source code (lower priority to avoid noise)\n if (x.endsWith('.ts') || x.endsWith('.tsx') || x.endsWith('.js') || x.endsWith('.jsx') ||\n x.endsWith('.py') || x.endsWith('.go') || x.endsWith('.rs') || x.endsWith('.java')) return 6;\n \n // Other\n return 7;\n };\n \n return [...paths].sort((a, b) => {\n const bucketA = getBucket(a);\n const bucketB = getBucket(b);\n if (bucketA !== bucketB) return bucketA - bucketB;\n // Within same bucket, sort alphabetically\n return a.localeCompare(b);\n });\n}\n\n/**\n * Flatten tree into display rows with depth information\n */\nfunction flattenTreeToRows(node: FsTreeNode, depth: number, rows: FsTreeDisplayRow[], errorMap?: Map<string, { code: string; message: string }>): void {\n const row: FsTreeDisplayRow = {\n path: node.path,\n name: node.name,\n type: node.type,\n depth,\n size: node.size,\n mtime: node.mtime,\n ext: node.ext,\n hidden: node.hidden,\n ignored: node.ignored,\n };\n \n // Check if this node has an associated error\n if (errorMap?.has(node.path)) {\n row.error = errorMap.get(node.path);\n } else if (node.type === 'other' && node.name === '<readdir_error>') {\n row.error = {\n code: 'INTERNAL',\n message: 'Failed to read directory',\n };\n }\n \n rows.push(row);\n \n if (node.children) {\n for (const child of node.children) {\n flattenTreeToRows(child, depth + 1, rows, errorMap);\n }\n }\n}\n\nasync function buildTree(\n absPath: string,\n relPath: string,\n depth: number,\n maxDepth: number,\n only: 'all' | 'files' | 'dirs',\n includeHidden: boolean,\n maxEntries: number,\n currentCount: { value: number },\n ignoredCount: { value: number },\n summary: FsSummary,\n extCounts: Map<string, number>,\n detail: 'basic' | 'stat' | 'digest',\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration,\n truncated: { reason?: 'MAX_ENTRIES' | 'MAX_DEPTH' },\n errorMap?: Map<string, { code: string; message: string }>\n): Promise<FsTreeNode | null> {\n if (currentCount.value >= maxEntries) {\n truncated.reason = 'MAX_ENTRIES';\n return null;\n }\n\n if (depth > maxDepth) {\n truncated.reason = 'MAX_DEPTH';\n return null;\n }\n\n const entryRel = relPath === '.' ? '.' : relPath.replace(/\\\\/g, '/');\n let stat;\n \n try {\n stat = await fs.lstat(absPath);\n } catch (e: any) {\n // Non-fatal: create error node instead of throwing\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n summary.total_entries++;\n \n const node: FsTreeNode = {\n name: path.basename(relPath) || relPath,\n type: 'other',\n path: entryRel,\n hidden: path.basename(relPath)?.startsWith('.'),\n ignored: false,\n };\n \n // Store error for display rows\n if (errorMap) {\n errorMap.set(entryRel, {\n code: errorCode,\n message: `Failed to stat: ${errorMessage}`,\n });\n }\n \n if (only === 'files' || only === 'dirs') return null;\n currentCount.value++;\n return node;\n }\n\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (stat.isDirectory()) type = 'dir';\n else if (stat.isFile()) type = 'file';\n else if (stat.isSymbolicLink()) type = 'symlink';\n\n const ignoreResult = shouldIgnore(entryRel, stat.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n summary.ignored++;\n return null;\n }\n\n summary.total_entries++;\n if (type === 'file') summary.files++;\n else if (type === 'dir') summary.dirs++;\n else if (type === 'symlink') summary.symlinks++;\n\n const isHidden = path.basename(relPath)?.startsWith('.');\n if (isHidden) summary.hidden++;\n\n const ext = type === 'file' ? path.extname(path.basename(relPath) || relPath).slice(1) : undefined;\n if (ext && (detail === 'stat' || detail === 'digest')) {\n extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n if (type === 'file' && (detail === 'stat' || detail === 'digest')) {\n summary.total_file_bytes = (summary.total_file_bytes ?? 0) + (stat.size ?? 0);\n }\n\n const node: FsTreeNode = {\n name: path.basename(relPath) || relPath,\n type,\n path: entryRel,\n size: (detail === 'stat' || detail === 'digest') && stat.isFile() ? stat.size : undefined,\n mtime: (detail === 'stat' || detail === 'digest') ? Math.floor(stat.mtimeMs / 1000) : undefined,\n ext,\n hidden: isHidden,\n ignored: false,\n };\n\n if (only === 'files' && type !== 'file' && type !== 'symlink') return null;\n if (only === 'dirs' && type !== 'dir') return null;\n\n currentCount.value++;\n\n if (type === 'dir' && depth < maxDepth) {\n let entries: Dirent[];\n let readdirError: { code: string; message: string } | undefined;\n \n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch (e: any) {\n // Non-fatal: log error but continue with empty children\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n readdirError = {\n code: errorCode,\n message: errorMessage,\n };\n entries = [];\n }\n\n const filtered = includeHidden ? entries : entries.filter((e: Dirent) => !e.name.startsWith('.'));\n\n filtered.sort((a: Dirent, b: Dirent) => {\n const aIsDir = a.isDirectory() ? 0 : 1;\n const bIsDir = b.isDirectory() ? 0 : 1;\n if (aIsDir !== bIsDir) return aIsDir - bIsDir;\n return a.name.localeCompare(b.name);\n });\n\n const children: FsTreeNode[] = [];\n\n // If readdir failed, store error for display rows\n if (readdirError && errorMap) {\n errorMap.set(entryRel, {\n code: readdirError.code,\n message: `Failed to read directory: ${readdirError.message}`,\n });\n }\n\n for (const entry of filtered) {\n if (currentCount.value >= maxEntries) break;\n\n const childAbs = path.join(absPath, entry.name);\n const childRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n const childRel = childRelPath.replace(/\\\\/g, '/');\n\n const preIgnore = shouldIgnore(childRel, entry.isDirectory(), ignoreCtx, cfg);\n if (preIgnore.shouldIgnore) {\n ignoredCount.value++;\n summary.ignored++;\n continue;\n }\n\n try {\n const child = await buildTree(\n childAbs,\n childRelPath,\n depth + 1,\n maxDepth,\n only,\n includeHidden,\n maxEntries,\n currentCount,\n ignoredCount,\n summary,\n extCounts,\n detail,\n ignoreCtx,\n cfg,\n truncated,\n errorMap\n );\n\n if (child) children.push(child);\n } catch (e: any) {\n // Non-fatal: log error for this path but continue with other entries\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e) ?? 'Unknown error';\n \n // Store error for display rows\n if (errorMap) {\n errorMap.set(childRel, {\n code: errorCode,\n message: `Failed to build subtree: ${errorMessage}`,\n });\n }\n \n // Create an error node to indicate this subtree failed\n summary.total_entries++;\n const errorNode: FsTreeNode = {\n name: path.basename(childRelPath) || childRelPath,\n type: 'other',\n path: childRel,\n hidden: path.basename(childRelPath)?.startsWith('.'),\n ignored: false,\n };\n \n if (only === 'files' || only === 'dirs') {\n // Skip error nodes if filtering by type\n continue;\n }\n \n currentCount.value++;\n children.push(errorNode);\n }\n }\n\n if (children.length > 0) node.children = children;\n }\n\n return node;\n}\n\n/**\n * Executer for fs_tree tool\n */\nexport class FsTreeExecuter extends BaseExecuter<FsTreeArgs, FsTreeOutput> {\n protected async executeTool(args: FsTreeArgs): Promise<FsTreeOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path);\n\n const maxDepth = Math.min(Math.max(args.max_depth ?? 3, 1), 20);\n const only = args.only ?? 'all';\n const includeHidden = args.include_hidden ?? false;\n const maxEntries = Math.min(Math.max(args.max_entries ?? 5000, 1), 20000);\n const detail = args.detail ?? 'stat';\n const includeDisplay = args.include_display ?? false;\n const maxDisplayRows = Math.min(Math.max(args.max_display_rows ?? 2000, 1), 20000);\n\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n throw toolErr('NOT_A_DIRECTORY', 'Path is not a directory.', {\n path: rel,\n hint: 'The path must point to a directory to build a tree. Provide a directory path, not a file.',\n });\n }\n } catch (e: any) {\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to build tree.');\n }\n\n const ignoreCtx = { directory_id: directoryId, workspace_id: args.workspace_id, directory_path: directory.path };\n\n const truncated = { reason: undefined as 'MAX_ENTRIES' | 'MAX_DEPTH' | undefined };\n const currentCount = { value: 0 };\n const ignoredCount = { value: 0 };\n const summary: FsSummary = {\n total_entries: 0,\n files: 0,\n dirs: 0,\n symlinks: 0,\n hidden: 0,\n ignored: 0,\n total_file_bytes: 0,\n };\n const extCounts = new Map<string, number>();\n const errorMap = new Map<string, { code: string; message: string }>(); // Track errors by path\n\n const tree = await buildTree(\n absTarget,\n rel,\n 0,\n maxDepth,\n only,\n includeHidden,\n maxEntries,\n currentCount,\n ignoredCount,\n summary,\n extCounts,\n detail,\n ignoreCtx,\n this.config,\n truncated,\n errorMap\n );\n\n if (!tree) throw toolErr('INTERNAL', 'Failed to build tree (empty result).');\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n if (detail === 'digest' && extCounts.size > 0) {\n summary.by_ext = Array.from(extCounts.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n }\n\n const result: FsTreeOutput = {\n tree,\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n\n // Only include display rows when explicitly requested to keep payload small.\n if (includeDisplay) {\n const displayRows: FsTreeDisplayRow[] = [];\n flattenTreeToRows(tree, 0, displayRows, errorMap);\n if (displayRows.length > maxDisplayRows) {\n displayRows.length = maxDisplayRows;\n // If we truncated display rows, reflect truncation for callers.\n result.truncated = result.truncated ?? {\n reason: 'MAX_ENTRIES',\n continuation: 'Display rows truncated; reduce max_entries/max_depth or lower max_display_rows',\n };\n }\n result.display = { rows: displayRows };\n }\n\n if (truncated.reason) {\n result.truncated = {\n reason: truncated.reason,\n continuation:\n truncated.reason === 'MAX_ENTRIES'\n ? 'Reduce max_entries or list this folder with fs_list instead'\n : 'Reduce max_depth or list this folder with fs_list instead',\n };\n }\n\n // summary rules\n if (detail === 'digest' || args.include_summary) {\n result.summary = summary;\n }\n\n // extras\n const extras: FsTreeOutput['extras'] = {};\n\n if (args.grep?.query) {\n try {\n const grepExecuter = new FsGrepExecuter(this.config);\n const grepArgs: FsGrepArgs = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n path: args.path ?? '.',\n query: args.grep.query,\n mode: args.grep.mode ?? 'substring',\n file_glob: args.grep.file_glob,\n max_files: args.grep.max_files ?? 2000,\n max_matches: args.grep.max_matches ?? 200,\n context_lines: args.grep.context_lines ?? 2,\n case_sensitive: args.grep.case_sensitive ?? false,\n };\n const grepResult = await grepExecuter.execute(grepArgs);\n \n if (grepResult.ok) {\n extras.grep = {\n matches: grepResult.data.matches,\n meta: grepResult.data.meta,\n context: grepResult.data.context,\n };\n }\n } catch (e: any) {\n // Non-fatal: if grep fails, just skip it\n // Tree result is still valid without grep extras\n }\n }\n\n const explicit = args.read?.paths?.filter(Boolean) ?? [];\n let auto: string[] = [];\n\n if (args.read?.auto) {\n const maxFiles = Math.min(Math.max(args.read.auto.max_files ?? 10, 1), 50);\n const collected: string[] = [];\n collectFilePaths(tree, collected, 3000);\n auto = rankImportant(collected).slice(0, maxFiles);\n }\n\n const merged = Array.from(new Set([...explicit, ...auto])).slice(0, 50);\n\n if (merged.length > 0) {\n try {\n const limitEach = Math.min(Math.max(args.read?.auto?.max_bytes_each ?? 20000, 1), 200000);\n const readManyExecuter = new FsReadManyExecuter(this.config);\n const readManyArgs: FsReadManyArgs = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n default_limit: limitEach,\n default_encoding: 'utf-8',\n items: merged.map((p) => ({ path: p })),\n };\n const readResult = await readManyExecuter.execute(readManyArgs);\n \n if (readResult.ok) {\n extras.read_many = {\n files: readResult.data.files.map((f) => ({\n path: f.path,\n content: f.content,\n bytes_read: f.bytes_read,\n truncated: f.truncated,\n error: f.error,\n })),\n context: readResult.data.context,\n };\n }\n } catch (e: any) {\n // Non-fatal: if read_many fails, just skip it\n // Tree result is still valid without read_many extras\n }\n }\n\n if (Object.keys(extras).length > 0) {\n result.extras = extras;\n }\n\n // Audit successful tree operation\n auditFsOperation('tree', context, true, undefined, {\n file_count: currentCount.value,\n });\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_tree tool\n */\nexport async function executeFsTree(\n config: Configuration,\n args: FsTreeArgs\n): Promise<ToolResult<FsTreeOutput>> {\n const executer = new FsTreeExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsGrepArgs, FsGrepOutput, FsGrepMatch } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Simple glob pattern matcher for file paths\n */\nfunction matchesFileGlob(relPath: string, fileGlob: string): boolean {\n // Convert glob to regex\n let regexStr = '^';\n let i = 0;\n while (i < fileGlob.length) {\n const char = fileGlob[i];\n if (char === '*') {\n if (i + 1 < fileGlob.length && fileGlob[i + 1] === '*') {\n regexStr += '.*';\n i += 2;\n } else {\n regexStr += '[^/]*';\n i++;\n }\n } else if (char === '?') {\n regexStr += '[^/]';\n i++;\n } else if (char === '{') {\n // Handle {ts,js,md} patterns\n const end = fileGlob.indexOf('}', i);\n if (end === -1) {\n regexStr += '\\\\{';\n i++;\n } else {\n const alternatives = fileGlob.substring(i + 1, end).split(',');\n regexStr += '(' + alternatives.map((alt) => alt.trim().replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|') + ')';\n i = end + 1;\n }\n } else if ('\\\\^$|.+()[]'.includes(char!)) {\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i');\n return regex.test(relPath);\n } catch {\n return false;\n }\n}\n\nasync function searchInFile(\n absPath: string,\n relPath: string,\n query: string,\n mode: 'substring' | 'regex',\n caseSensitive: boolean,\n contextLines: number,\n maxMatches: number,\n matches: FsGrepMatch[]\n): Promise<number> {\n let content: string;\n try {\n content = await fs.readFile(absPath, 'utf-8');\n } catch {\n // Skip files we can't read\n return 0;\n }\n\n const lines = content.split(/\\r?\\n/);\n let found = 0;\n\n let regex: RegExp;\n if (mode === 'regex') {\n try {\n regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n } catch {\n // Invalid regex, fall back to substring\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n regex = new RegExp(escaped, caseSensitive ? 'g' : 'gi');\n }\n } else {\n const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n regex = new RegExp(escaped, caseSensitive ? 'g' : 'gi');\n }\n\n for (let i = 0; i < lines.length && found < maxMatches; i++) {\n const line = lines[i]!;\n if (regex.test(line)) {\n // Reset regex lastIndex for next iteration\n regex.lastIndex = 0;\n\n const startLine = Math.max(0, i - contextLines);\n const endLine = Math.min(lines.length - 1, i + contextLines);\n const snippet = lines.slice(startLine, endLine + 1);\n\n matches.push({\n path: relPath,\n line: i + 1, // 1-indexed\n preview: line.trim(),\n snippet,\n });\n found++;\n }\n }\n\n return found;\n}\n\nasync function grepDirectory(\n absPath: string,\n relPath: string,\n rootPath: string,\n query: string,\n mode: 'substring' | 'regex',\n fileGlob: string | undefined,\n caseSensitive: boolean,\n contextLines: number,\n maxFiles: number,\n maxMatches: number,\n filesScanned: { value: number },\n matches: FsGrepMatch[],\n ignoredCount: { value: number },\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration\n): Promise<void> {\n if (filesScanned.value >= maxFiles || matches.length >= maxMatches) {\n return;\n }\n\n let entries;\n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch {\n // Skip directories we can't read\n return;\n }\n\n for (const entry of entries) {\n if (filesScanned.value >= maxFiles || matches.length >= maxMatches) break;\n\n const entryAbsPath = path.join(absPath, entry.name);\n const entryRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, entry.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n // Never recurse into ignored directories\n continue;\n }\n\n if (entry.isFile()) {\n // Check file_glob filter\n if (fileGlob && !matchesFileGlob(entryRelPath, fileGlob)) {\n continue;\n }\n\n filesScanned.value++;\n await searchInFile(entryAbsPath, entryRelPath, query, mode, caseSensitive, contextLines, maxMatches - matches.length, matches);\n } else if (entry.isDirectory()) {\n // Recurse into directories\n await grepDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n fileGlob,\n caseSensitive,\n contextLines,\n maxFiles,\n maxMatches,\n filesScanned,\n matches,\n ignoredCount,\n ignoreCtx,\n cfg\n );\n }\n }\n}\n\n/**\n * Executer for fs_grep tool\n */\nexport class FsGrepExecuter extends BaseExecuter<FsGrepArgs, FsGrepOutput> {\n protected async executeTool(args: FsGrepArgs): Promise<FsGrepOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n\n const query = args.query;\n if (!query || query.length === 0) {\n throw toolErr('INVALID_INPUT', 'Query is required.', {\n hint: 'Query should be a search pattern to find in file contents. Use a substring (default) or regex pattern (with mode=\"regex\"). Examples: \"function\", \"import.*from\", \"TODO\"',\n });\n }\n\n const mode = args.mode ?? 'substring';\n const fileGlob = args.file_glob;\n const maxFiles = Math.min(Math.max(args.max_files ?? 2000, 1), 10000);\n const maxMatches = Math.min(Math.max(args.max_matches ?? 200, 1), 1000);\n const contextLines = Math.min(Math.max(args.context_lines ?? 2, 0), 10);\n const caseSensitive = args.case_sensitive ?? false;\n\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path ?? '.');\n\n // Check that starting path is a directory (if provided and not \".\")\n if (rel !== '.') {\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n throw toolErr('NOT_A_DIRECTORY', 'Grep path is not a directory.', {\n path: rel,\n hint: 'The grep path must be a directory. Grep searches within directories recursively. Use \".\" to search from the root, or provide a directory path.',\n });\n }\n } catch (e: any) {\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to stat grep path.');\n }\n }\n\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const matches: FsGrepMatch[] = [];\n const filesScanned = { value: 0 };\n const ignoredCount = { value: 0 };\n\n await grepDirectory(absTarget, rel, directory.path, query, mode, fileGlob, caseSensitive, contextLines, maxFiles, maxMatches, filesScanned, matches, ignoredCount, ignoreCtx, this.config);\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: rel,\n });\n\n // Audit successful grep operation\n auditFsOperation('grep', context, true, undefined, {\n file_count: filesScanned.value,\n match_count: matches.length,\n });\n\n return {\n matches,\n meta: {\n files_scanned: filesScanned.value,\n matches: matches.length,\n truncated: filesScanned.value >= maxFiles || matches.length >= maxMatches,\n },\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n }\n}\n\n/**\n * Convenience function to execute fs_grep tool\n */\nexport async function executeFsGrep(\n config: Configuration,\n args: FsGrepArgs\n): Promise<ToolResult<FsGrepOutput>> {\n const executer = new FsGrepExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\nimport type { ToolResult, ToolError, FsReadManyArgs, FsReadManyOutput, FsReadManyItem } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { requireDirectory, makeContext, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\nimport { FsReadExecuter } from './fs-read.js';\nimport type { FsReadArgs } from '@devicelink-workspace/domain';\nimport isEmpty from 'lodash/isEmpty.js';\nimport { shouldIgnore } from '../util/ignore.js';\n\n/**\n * Executer for fs_read_many tool\n */\nexport class FsReadManyExecuter extends BaseExecuter<FsReadManyArgs, FsReadManyOutput> {\n protected async executeTool(args: FsReadManyArgs): Promise<FsReadManyOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n const defaultLimit = args.default_limit ?? 12000;\n const defaultEncoding = args.default_encoding ?? 'utf-8';\n\n // Normalize input: accept either items[] or paths[]\n let normalizedItems: FsReadManyItem[] = [];\n \n if (args.items && Array.isArray(args.items)) {\n normalizedItems = args.items;\n }\n\n if (isEmpty(normalizedItems)) {\n throw toolErr(\n 'INVALID_INPUT',\n 'fs_read_many expects { items: [{path,...}] }',\n {\n receivedKeys: Object.keys(args ?? {}),\n hint: 'Provide an \"items\" array with at least one object containing a \"path\" property. Each item can optionally include \"offset\", \"limit\", and \"encoding\". Example: { items: [{ path: \"file1.ts\" }, { path: \"file2.ts\", limit: 5000 }] }',\n }\n );\n }\n\n const files: FsReadManyOutput['files'] = [];\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const readExecuter = new FsReadExecuter(this.config);\n\n for (const item of normalizedItems) {\n try {\n // Check denylist and ignore rules before attempting read\n const ignoreResult = shouldIgnore(item.path, false, ignoreCtx, this.config);\n if (ignoreResult.shouldIgnore) {\n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: 'PERMISSION_DENIED',\n message: `Access denied: ${ignoreResult.reason || ignoreResult.matchedRule || 'blocked'}`,\n },\n });\n continue;\n }\n\n const readArgs: FsReadArgs = {\n directory_id: directoryId,\n path: item.path,\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n offset: item.offset ?? 0,\n limit: item.limit ?? defaultLimit,\n encoding: item.encoding ?? defaultEncoding,\n };\n\n const result = await readExecuter.execute(readArgs);\n \n if (!result.ok) {\n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: result.error.code,\n message: result.error.message,\n },\n });\n continue;\n }\n\n files.push({\n path: item.path,\n content: result.data.content,\n bytes_read: result.data.bytes_read,\n truncated: !result.data.eof,\n });\n } catch (e: any) {\n // Extract structured error from ToolError if available\n const toolError = e as ToolError;\n const errorCode = toolError?.code ?? 'INTERNAL';\n const errorMessage = toolError?.message ?? e?.message ?? String(e);\n \n files.push({\n path: item.path,\n content: '',\n bytes_read: 0,\n truncated: false,\n error: {\n code: errorCode,\n message: errorMessage,\n },\n });\n }\n }\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: '.',\n });\n\n auditFsOperation('read_many', context, true, undefined, {\n file_count: files.length,\n });\n\n return {\n files,\n context,\n };\n }\n}\n\n/**\n * Convenience function to execute fs_read_many tool\n */\nexport async function executeFsReadMany(\n config: Configuration,\n args: FsReadManyArgs\n): Promise<ToolResult<FsReadManyOutput>> {\n const executer = new FsReadManyExecuter(config);\n return await executer.execute(args);\n}\n", "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Configuration } from '../../../core/configuration.js';\nimport type { FsSearchEntry, FsSearchOutput, FsSearchArgs, PaginationMeta, ToolMessage } from '@devicelink-workspace/domain';\nimport type { ToolResult } from '@devicelink-workspace/domain';\nimport { BaseExecuter } from './base-executer.js';\nimport { shouldIgnore } from '../util/ignore.js';\nimport { requireDirectory, resolveInRoot, makeContext, mapFsError, toolErr } from '../util/_util.js';\nimport { auditFsOperation } from '../util/_audit.js';\n\n/**\n * Simple glob pattern matcher\n * Supports: *, **, ?, [chars], [!chars]\n * Basic implementation - not as full-featured as minimatch but sufficient for common patterns\n */\nfunction matchesGlob(name: string, pattern: string): boolean {\n // Convert glob pattern to regex\n let regexStr = '^';\n let i = 0;\n while (i < pattern.length) {\n const char = pattern[i];\n if (char === '*') {\n if (i + 1 < pattern.length && pattern[i + 1] === '*') {\n // ** matches any number of directories\n regexStr += '.*';\n i += 2;\n } else {\n // * matches any characters except path separator\n regexStr += '[^/\\\\\\\\]*';\n i++;\n }\n } else if (char === '?') {\n // ? matches any single character except path separator\n regexStr += '[^/\\\\\\\\]';\n i++;\n } else if (char === '[') {\n // Character class\n const end = pattern.indexOf(']', i);\n if (end === -1) {\n regexStr += '\\\\[';\n i++;\n } else {\n const classContent = pattern.substring(i + 1, end);\n if (classContent.startsWith('!')) {\n regexStr += '[^' + classContent.substring(1) + ']';\n } else {\n regexStr += '[' + classContent + ']';\n }\n i = end + 1;\n }\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\n // Escape special regex characters\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i'); // case-insensitive\n return regex.test(name);\n } catch {\n // If regex is invalid, fall back to substring match\n return name.toLowerCase().includes(pattern.toLowerCase());\n }\n}\n\nfunction matchesQuery(name: string, query: string, mode: 'substring' | 'glob'): boolean {\n if (mode === 'glob') {\n return matchesGlob(name, query);\n }\n // substring mode (case-insensitive)\n return name.toLowerCase().includes(query.toLowerCase());\n}\n\n/**\n * Calculate ranking score for search results\n */\nfunction calculateScore(entry: { name: string; path: string }, prefer_paths?: string[], avoid_paths?: string[]): number {\n let score = 100; // base score\n\n // Boost if path matches prefer_paths\n if (prefer_paths) {\n for (const prefer of prefer_paths) {\n if (entry.path.startsWith(prefer)) {\n score += 50;\n break;\n }\n }\n }\n\n // Penalize if path matches avoid_paths\n if (avoid_paths) {\n for (const avoid of avoid_paths) {\n if (entry.path.startsWith(avoid)) {\n score -= 30;\n break;\n }\n }\n }\n\n // Boost exact name matches\n if (entry.name === entry.path.split('/').pop()) {\n score += 20;\n }\n\n return score;\n}\n\n/**\n * Check if path matches file_glob pattern\n */\nfunction matchesFileGlob(relPath: string, fileGlob: string): boolean {\n // Simple glob matching for file patterns\n // Convert glob to regex (similar to matchesGlob but for full paths)\n let regexStr = '^';\n let i = 0;\n while (i < fileGlob.length) {\n const char = fileGlob[i];\n if (char === '*') {\n if (i + 1 < fileGlob.length && fileGlob[i + 1] === '*') {\n regexStr += '.*';\n i += 2;\n } else {\n regexStr += '[^/]*';\n i++;\n }\n } else if (char === '?') {\n regexStr += '[^/]';\n i++;\n } else if ('\\\\^$|.+(){}[]'.includes(char!)) {\n regexStr += '\\\\' + char;\n i++;\n } else {\n regexStr += char;\n i++;\n }\n }\n regexStr += '$';\n\n try {\n const regex = new RegExp(regexStr, 'i');\n return regex.test(relPath);\n } catch {\n return false;\n }\n}\n\nasync function searchDirectory(\n absPath: string,\n relPath: string,\n rootPath: string,\n query: string,\n mode: 'substring' | 'glob',\n recursive: boolean,\n only: 'all' | 'files' | 'dirs',\n includeHidden: boolean,\n maxResults: number,\n results: FsSearchEntry[],\n ignoredCount: { value: number },\n ignoreCtx: { directory_id: string; workspace_id?: string; directory_path: string },\n cfg: Configuration,\n fileGlob?: string,\n preferPaths?: string[],\n avoidPaths?: string[],\n includeStats?: boolean\n): Promise<void> {\n if (results.length >= maxResults) {\n return;\n }\n\n let entries;\n try {\n entries = await fs.readdir(absPath, { withFileTypes: true });\n } catch (e) {\n // If we can't read the directory, skip it\n return;\n }\n\n // Filter hidden files\n const visibleEntries = includeHidden ? entries : entries.filter((e) => !e.name.startsWith('.'));\n\n for (const entry of visibleEntries) {\n if (results.length >= maxResults) break;\n\n const entryAbsPath = path.join(absPath, entry.name);\n const entryRelPath = relPath === '.' ? entry.name : path.posix.join(relPath, entry.name);\n\n // Check ignore rules - always filter ignored entries\n const ignoreResult = shouldIgnore(entryRelPath, entry.isDirectory(), ignoreCtx, cfg);\n if (ignoreResult.shouldIgnore) {\n ignoredCount.value++;\n // Never recurse into ignored directories - skip them entirely\n continue;\n }\n\n // Check file_glob filter\n if (fileGlob && !matchesFileGlob(entryRelPath, fileGlob)) {\n // Still recurse into directories if recursive\n if (recursive && entry.isDirectory()) {\n await searchDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults,\n results,\n ignoredCount,\n ignoreCtx,\n cfg,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n }\n continue;\n }\n\n // Check if name matches query\n const matches = matchesQuery(entry.name, query, mode);\n\n let type: 'file' | 'dir' | 'symlink' | 'other' = 'other';\n if (entry.isDirectory()) type = 'dir';\n else if (entry.isFile()) type = 'file';\n else if (entry.isSymbolicLink()) type = 'symlink';\n\n // Apply filter\n const shouldInclude =\n matches &&\n (only === 'all' || (only === 'files' && (type === 'file' || type === 'symlink')) || (only === 'dirs' && type === 'dir'));\n\n if (shouldInclude) {\n // Get stat for metadata (if includeStats is true or undefined)\n let size: number | undefined;\n let mtime: number | undefined;\n if (includeStats !== false) {\n try {\n const st = await fs.stat(entryAbsPath);\n size = st.isFile() ? st.size : undefined;\n mtime = Math.floor(st.mtimeMs / 1000);\n } catch {\n // Stat failed, continue without size/mtime\n }\n }\n\n const ext = type === 'file' ? path.extname(entry.name).slice(1) : undefined;\n\n // Calculate ranking score\n const score = calculateScore({ name: entry.name, path: entryRelPath }, preferPaths, avoidPaths);\n\n results.push({\n name: entry.name,\n path: entryRelPath,\n type,\n size,\n mtime,\n ext,\n hidden: entry.name.startsWith('.'),\n ignored: false, // already filtered out ignored entries\n score,\n matched: 'name',\n });\n }\n\n // Recurse into directories if recursive is true\n if (recursive && type === 'dir') {\n await searchDirectory(\n entryAbsPath,\n entryRelPath,\n rootPath,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults,\n results,\n ignoredCount,\n ignoreCtx,\n cfg,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n }\n }\n}\n\n/**\n * Executer for fs_search tool\n */\nexport class FsSearchExecuter extends BaseExecuter<FsSearchArgs, FsSearchOutput> {\n protected async executeTool(args: FsSearchArgs): Promise<FsSearchOutput> {\n const directoryId = args.directory_id;\n const directory = requireDirectory(this.config, directoryId);\n\n const query = args.query;\n if (!query || query.length === 0) {\n throw toolErr('INVALID_INPUT', 'Query is required.', {\n hint: 'Query should be a pattern to match file or directory names. Use a substring (default) or glob pattern (with mode=\"glob\"). Examples: \"config\", \"*.ts\", \"test/**\"',\n });\n }\n\n const mode = args.mode ?? 'substring';\n const recursive = args.recursive ?? true;\n const only = args.only ?? 'all';\n const includeHidden = args.include_hidden ?? false;\n const maxResults = Math.min(Math.max(args.max_results ?? 200, 1), 20000);\n const offset = Math.max(args.offset ?? 0, 0);\n const fileGlob = args.file_glob;\n const preferPaths = args.prefer_paths;\n const avoidPaths = args.avoid_paths;\n const includeStats = args.include_stats !== false; // default true\n\n const { absTarget, rel } = await resolveInRoot(directory.path, args.path ?? '.');\n\n let searchPath = absTarget;\n let searchRelPath = rel;\n const messages: ToolMessage[] = [];\n\n // Check that starting path is a directory (if provided and not \".\")\n if (rel !== '.') {\n try {\n const st = await fs.stat(absTarget);\n if (!st.isDirectory()) {\n // If it's a file, search the directory containing it\n if (st.isFile()) {\n searchPath = path.dirname(absTarget);\n const parentRelPath = path.posix.dirname(rel);\n searchRelPath = parentRelPath === '.' ? '.' : parentRelPath;\n messages.push({\n type: 'warning',\n description: `Search path \"${rel}\" is not a directory (it's a file). Searching the directory containing it instead: \"${searchRelPath}\"`,\n });\n } else {\n throw toolErr('NOT_A_DIRECTORY', 'Search path is not a directory.', {\n path: rel,\n hint: 'The search path must be a directory. Search looks for files/directories matching the query within directories. Use \".\" to search from the root, or provide a directory path.',\n });\n }\n }\n } catch (e: any) {\n // If it's already a ToolError, rethrow\n if (e?.code && e?.message && typeof e?.code === 'string') throw e;\n throw mapFsError(e, 'Failed to stat search path.');\n }\n }\n\n const ignoreCtx = {\n directory_id: directoryId,\n workspace_id: args.workspace_id,\n directory_path: directory.path,\n };\n\n const allResults: FsSearchEntry[] = [];\n const ignoredCount = { value: 0 };\n await searchDirectory(\n searchPath,\n searchRelPath,\n directory.path,\n query,\n mode,\n recursive,\n only,\n includeHidden,\n maxResults + offset, // Search more to account for offset\n allResults,\n ignoredCount,\n ignoreCtx,\n this.config,\n fileGlob,\n preferPaths,\n avoidPaths,\n includeStats\n );\n\n // Sort by score (higher first), then by name\n allResults.sort((a, b) => {\n const scoreDiff = (b.score ?? 0) - (a.score ?? 0);\n if (scoreDiff !== 0) return scoreDiff;\n return a.name.localeCompare(b.name);\n });\n\n // Apply pagination\n const page = allResults.slice(offset, offset + maxResults);\n const next_offset = offset + page.length;\n const has_more = next_offset < allResults.length;\n\n const meta: PaginationMeta = {\n count: page.length,\n limit: maxResults,\n offset,\n has_more,\n next_offset: has_more ? next_offset : undefined,\n };\n\n const context = makeContext({\n workspace_id: args.workspace_id,\n device_id: args.device_id,\n directory_id: directoryId,\n path: searchRelPath,\n });\n\n // Audit successful search operation\n auditFsOperation('search', context, true, undefined, {\n file_count: page.length,\n });\n\n const result: FsSearchOutput = {\n results: page,\n meta,\n context,\n filtered: { ignored_count: ignoredCount.value },\n };\n if (messages.length > 0) {\n result.messages = messages as ToolMessage[];\n }\n\n return result;\n }\n}\n\n/**\n * Convenience function to execute fs_search tool\n */\nexport async function executeFsSearch(\n config: Configuration,\n args: FsSearchArgs\n): Promise<ToolResult<FsSearchOutput>> {\n const executer = new FsSearchExecuter(config);\n return await executer.execute(args);\n}\n", "import type { Configuration } from '../../../core/configuration.js';\r\nimport { fail } from '@devicelink-workspace/domain';\r\nimport type { ToolResult, ToolError } from '@devicelink-workspace/domain';\r\nimport { BaseExecuter } from './base-executer.js';\r\nimport { FsListExecuter } from './fs-list.js';\r\nimport { FsReadExecuter } from './fs-read.js';\r\nimport { FsInfoExecuter } from './fs-info.js';\r\nimport { FsTreeExecuter } from './fs-tree.js';\r\nimport { FsSearchExecuter } from './fs-search.js';\r\nimport { FsGrepExecuter } from './fs-grep.js';\r\nimport { FsReadManyExecuter } from './fs-read-many.js';\r\nimport type { ToolName, ToolArgs, ToolOutput } from './types.js';\r\n\r\n/**\r\n * Type guard to check if an error is a ToolError\r\n */\r\nfunction isToolError(e: unknown): e is ToolError {\r\n return (\r\n typeof e === 'object' &&\r\n e !== null &&\r\n 'code' in e &&\r\n 'message' in e &&\r\n typeof (e as any).code === 'string' &&\r\n typeof (e as any).message === 'string'\r\n );\r\n}\r\n\r\n/**\r\n * Tool executer registry class\r\n * Manages tool executers and provides a unified interface for executing tools\r\n */\r\nexport class ToolExecuterRegistry {\r\n private readonly config: Configuration;\r\n private readonly executers: Map<ToolName, BaseExecuter<any, any>> = new Map();\r\n\r\n constructor(config: Configuration) {\r\n this.config = config;\r\n this.initializeExecuters();\r\n }\r\n\r\n /**\r\n * Initialize all tool executers\r\n */\r\n private initializeExecuters(): void {\r\n this.executers.set('fs_list', new FsListExecuter(this.config));\r\n this.executers.set('fs_read', new FsReadExecuter(this.config));\r\n this.executers.set('fs_info', new FsInfoExecuter(this.config));\r\n this.executers.set('fs_tree', new FsTreeExecuter(this.config));\r\n this.executers.set('fs_search', new FsSearchExecuter(this.config));\r\n this.executers.set('fs_grep', new FsGrepExecuter(this.config));\r\n this.executers.set('fs_read_many', new FsReadManyExecuter(this.config));\r\n }\r\n\r\n /**\r\n * Execute a tool by name with properly typed arguments and return value\r\n *\r\n * @param toolName - Name of the tool to execute\r\n * @param args - Tool-specific arguments\r\n * @returns Tool result with typed output or error\r\n */\r\n public async executeTool(\r\n toolName: ToolName,\r\n args: ToolArgs\r\n ): Promise<ToolResult<ToolOutput>> {\r\n const executer = this.executers.get(toolName);\r\n\r\n if (!executer) {\r\n return fail({\r\n code: 'UNKNOWN_TOOL',\r\n message: `Unknown tool: ${toolName}`,\r\n details: { toolName },\r\n });\r\n }\r\n\r\n try {\r\n return await executer.execute(args);\r\n } catch (e: unknown) {\r\n if (isToolError(e)) {\r\n return fail(e);\r\n }\r\n return fail({\r\n code: 'INTERNAL',\r\n message: e instanceof Error ? e.message : 'Unknown error',\r\n details: { raw: String(e) },\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Get a specific executer instance by tool name\r\n *\r\n * @param toolName - Name of the tool\r\n * @returns The executer instance or undefined if not found\r\n */\r\n public getExecuter<T extends ToolName>(toolName: T): BaseExecuter<any, any> | undefined {\r\n return this.executers.get(toolName);\r\n }\r\n\r\n /**\r\n * Check if a tool is registered\r\n *\r\n * @param toolName - Name of the tool\r\n * @returns True if the tool is registered\r\n */\r\n public hasTool(toolName: string): toolName is ToolName {\r\n return this.executers.has(toolName as ToolName);\r\n }\r\n\r\n /**\r\n * Get all registered tool names\r\n *\r\n * @returns Array of all registered tool names\r\n */\r\n public getRegisteredTools(): ToolName[] {\r\n return Array.from(this.executers.keys());\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function to execute a tool (creates a registry instance)\r\n * This maintains backward compatibility with the function-based API\r\n *\r\n * @param config - CLI Configuration\r\n * @param toolName - Name of the tool to execute\r\n * @param args - Tool-specific arguments\r\n * @returns Tool result with typed output or error\r\n */\r\nexport async function executeTool(\r\n config: Configuration,\r\n toolName: ToolName,\r\n args: ToolArgs\r\n): Promise<ToolResult<ToolOutput>> {\r\n const registry = new ToolExecuterRegistry(config);\r\n return await registry.executeTool(toolName, args);\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport isObject from 'lodash/isObject.js';\r\nimport get from 'lodash/get.js';\r\n\r\n/**\r\n * Calculate execution timing from start time\r\n */\r\nexport function calculateTiming(startTime: number): {\r\n execution_ms: number;\r\n execution_sec: number;\r\n} {\r\n const executionMs = Date.now() - startTime;\r\n const executionSec = parseFloat((executionMs / 1000).toFixed(2));\r\n return {\r\n execution_ms: executionMs,\r\n execution_sec: executionSec,\r\n };\r\n}\r\n\r\n/**\r\n * Check if a value is a ToolResult envelope (has 'ok' property)\r\n */\r\nexport function isToolResultEnvelope(value: unknown): value is ToolResult<unknown> {\r\n return isObject(value) && typeof get(value, 'ok') === 'boolean';\r\n}\r\n\r\n/**\r\n * Extract data from ToolResult envelope\r\n * Handles both envelope format (ok/data/error) and raw results\r\n */\r\nexport function extractToolResult<T = unknown>(\r\n raw: ToolResult<T> | T\r\n): {\r\n ok: boolean;\r\n result?: T;\r\n error?: unknown;\r\n messages?: unknown[];\r\n} {\r\n const hasEnvelope = isToolResultEnvelope(raw);\r\n const ok = hasEnvelope ? Boolean(get(raw, 'ok')) : true;\r\n \r\n let result: T | undefined;\r\n let error: unknown;\r\n let messages: unknown[] | undefined;\r\n\r\n if (ok) {\r\n // Success case\r\n if (hasEnvelope) {\r\n result = get(raw, 'data') ?? get(raw, 'result') ?? (raw as T);\r\n } else {\r\n result = raw as T;\r\n }\r\n\r\n // Extract messages if present\r\n if (isObject(result) && Array.isArray(get(result, 'messages'))) {\r\n messages = get(result, 'messages') as unknown[];\r\n result = { ...(result as any) };\r\n delete (result as any).messages;\r\n }\r\n } else {\r\n // Error case\r\n if (hasEnvelope) {\r\n error = get(raw, 'error') ?? raw;\r\n } else {\r\n error = raw;\r\n }\r\n }\r\n\r\n return { ok, result, error, messages };\r\n}\r\n\r\n/**\r\n * Create a ToolResultResponse-compatible object from ToolResult\r\n */\r\nexport function formatToolResultResponse(\r\n jobId: string,\r\n toolName: string,\r\n raw: ToolResult<unknown> | unknown,\r\n startTime: number\r\n): {\r\n type: 'tool_result';\r\n job_id: string;\r\n tool: string;\r\n ok: boolean;\r\n result?: unknown;\r\n error?: unknown;\r\n messages?: unknown[];\r\n timing: {\r\n execution_ms: number;\r\n execution_sec: number;\r\n };\r\n} {\r\n const timing = calculateTiming(startTime);\r\n const { ok, result, error, messages } = extractToolResult(raw);\r\n\r\n const toolResult: any = {\r\n type: 'tool_result',\r\n job_id: jobId,\r\n tool: toolName,\r\n ok,\r\n timing,\r\n };\r\n\r\n if (ok) {\r\n toolResult.result = result ?? null;\r\n } else {\r\n toolResult.error = error ?? { code: 'UNKNOWN', message: 'Unknown error' };\r\n }\r\n\r\n if (messages) {\r\n toolResult.messages = messages;\r\n }\r\n\r\n return toolResult;\r\n}\r\n\r\n/**\r\n * Create an error ToolResultResponse\r\n */\r\nexport function formatToolErrorResponse(\r\n jobId: string,\r\n toolName: string,\r\n error: unknown,\r\n startTime: number\r\n): {\r\n type: 'tool_result';\r\n job_id: string;\r\n tool: string;\r\n ok: false;\r\n error: string | { code: string; message: string };\r\n timing: {\r\n execution_ms: number;\r\n execution_sec: number;\r\n };\r\n} {\r\n const timing = calculateTiming(startTime);\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n\r\n return {\r\n type: 'tool_result',\r\n job_id: jobId,\r\n tool: toolName,\r\n ok: false,\r\n error: errorMessage,\r\n timing,\r\n };\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport type { ToolName } from '../executers/types.js';\r\n\r\n/**\r\n * Base class for tool results\r\n * Provides common functionality and toString() method\r\n */\r\nexport abstract class BaseToolResult {\r\n public readonly toolName: ToolName;\r\n public readonly jobId: string;\r\n public readonly ok: boolean;\r\n public readonly elapsedSec: number;\r\n public readonly raw: ToolResult<unknown>;\r\n\r\n constructor(\r\n toolName: ToolName,\r\n jobId: string,\r\n raw: ToolResult<unknown>,\r\n elapsedSec: number\r\n ) {\r\n this.toolName = toolName;\r\n this.jobId = jobId;\r\n this.ok = raw.ok;\r\n this.elapsedSec = elapsedSec;\r\n this.raw = raw;\r\n }\r\n\r\n /**\r\n * Abstract method that subclasses must implement\r\n * Returns a human-readable description of what the tool did\r\n */\r\n protected abstract getDescription(): string;\r\n\r\n /**\r\n * Get status indicator (\u2713 for success, \u2717 for error)\r\n */\r\n protected getStatusIcon(): string {\r\n return this.ok ? '\u2713' : '\u2717';\r\n }\r\n\r\n /**\r\n * Get status text\r\n */\r\n protected getStatusText(): string {\r\n return this.ok ? 'SUCCESS' : 'FAILED';\r\n }\r\n\r\n /**\r\n * Format the result as a string\r\n */\r\n public toString(): string {\r\n const status = this.getStatusIcon();\r\n const description = this.getDescription();\r\n return `${status} ${this.toolName} (${description}, elapsed=${this.elapsedSec}s)`;\r\n }\r\n}\r\n", "import type { FsListOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsListResult extends BaseToolResult {\r\n private readonly output?: FsListOutput;\r\n\r\n constructor(\r\n toolName: 'fs_list',\r\n jobId: string,\r\n raw: ToolResult<FsListOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { items, meta, filtered, context } = this.output;\r\n const itemCount = items?.length ?? 0;\r\n const totalCount = meta?.count ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n const path = context?.path ?? 'unknown';\r\n\r\n const parts: string[] = [];\r\n \r\n if (itemCount > 0) {\r\n parts.push(`${itemCount} item${itemCount !== 1 ? 's' : ''}`);\r\n }\r\n \r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.has_more) {\r\n parts.push('has_more');\r\n }\r\n\r\n const description = parts.length > 0 ? parts.join(', ') : 'empty';\r\n return `path=${path}, ${description}`;\r\n }\r\n}\r\n", "import type { FsReadOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsReadResult extends BaseToolResult {\r\n private readonly output?: FsReadOutput;\r\n\r\n constructor(\r\n toolName: 'fs_read',\r\n jobId: string,\r\n raw: ToolResult<FsReadOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { bytes_read, eof, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const size = bytes_read ?? 0;\r\n const truncated = !eof;\r\n\r\n const parts: string[] = [`path=${path}`, `${size} bytes`];\r\n \r\n if (truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsInfoOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsInfoResult extends BaseToolResult {\r\n private readonly output?: FsInfoOutput;\r\n\r\n constructor(\r\n toolName: 'fs_info',\r\n jobId: string,\r\n raw: ToolResult<FsInfoOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { type, size, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const sizeStr = size !== undefined ? `${size} bytes` : 'no size';\r\n\r\n return `path=${path}, type=${type}, ${sizeStr}`;\r\n }\r\n}\r\n", "import type { FsTreeOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsTreeResult extends BaseToolResult {\r\n private readonly output?: FsTreeOutput;\r\n\r\n constructor(\r\n toolName: 'fs_tree',\r\n jobId: string,\r\n raw: ToolResult<FsTreeOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { tree, filtered, summary, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [`path=${path}`];\r\n\r\n if (summary) {\r\n const { total_entries, files, dirs } = summary;\r\n if (total_entries !== undefined) {\r\n parts.push(`${total_entries} entries`);\r\n }\r\n if (files !== undefined) {\r\n parts.push(`${files} files`);\r\n }\r\n if (dirs !== undefined) {\r\n parts.push(`${dirs} dirs`);\r\n }\r\n } else if (tree) {\r\n // Count nodes recursively\r\n const countNodes = (node: typeof tree): number => {\r\n let count = 1;\r\n if (node.children) {\r\n for (const child of node.children) {\r\n count += countNodes(child);\r\n }\r\n }\r\n return count;\r\n };\r\n const nodeCount = countNodes(tree);\r\n parts.push(`${nodeCount} nodes`);\r\n }\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (this.output.truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsSearchOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsSearchResult extends BaseToolResult {\r\n private readonly output?: FsSearchOutput;\r\n\r\n constructor(\r\n toolName: 'fs_search',\r\n jobId: string,\r\n raw: ToolResult<FsSearchOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { results, meta, filtered, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const resultCount = results?.length ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [`path=${path}`, `${resultCount} result${resultCount !== 1 ? 's' : ''}`];\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.has_more) {\r\n parts.push('has_more');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsGrepOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsGrepResult extends BaseToolResult {\r\n private readonly output?: FsGrepOutput;\r\n\r\n constructor(\r\n toolName: 'fs_grep',\r\n jobId: string,\r\n raw: ToolResult<FsGrepOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { matches, meta, filtered, context } = this.output;\r\n const path = context?.path ?? 'unknown';\r\n const matchCount = matches?.length ?? 0;\r\n const filesScanned = meta?.files_scanned ?? 0;\r\n const ignoredCount = filtered?.ignored_count ?? 0;\r\n\r\n const parts: string[] = [\r\n `path=${path}`,\r\n `${matchCount} match${matchCount !== 1 ? 'es' : ''}`,\r\n `${filesScanned} file${filesScanned !== 1 ? 's' : ''} scanned`,\r\n ];\r\n\r\n if (ignoredCount > 0) {\r\n parts.push(`${ignoredCount} ignored`);\r\n }\r\n\r\n if (meta?.truncated) {\r\n parts.push('truncated');\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { FsReadManyOutput } from '@devicelink-workspace/domain';\r\nimport type { ToolResult } from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\n\r\nexport class FsReadManyResult extends BaseToolResult {\r\n private readonly output?: FsReadManyOutput;\r\n\r\n constructor(\r\n toolName: 'fs_read_many',\r\n jobId: string,\r\n raw: ToolResult<FsReadManyOutput>,\r\n elapsedSec: number\r\n ) {\r\n super(toolName, jobId, raw, elapsedSec);\r\n this.output = raw.ok ? raw.data : undefined;\r\n }\r\n\r\n protected getDescription(): string {\r\n if (!this.ok) {\r\n const error = this.raw.error;\r\n if (error && typeof error === 'object' && 'message' in error) {\r\n return `error: ${String(error.message)}`;\r\n }\r\n return 'error';\r\n }\r\n\r\n if (!this.output) {\r\n return 'no result';\r\n }\r\n\r\n const { files } = this.output;\r\n const fileCount = files?.length ?? 0;\r\n const successCount = files?.filter((f) => !f.error).length ?? 0;\r\n const errorCount = fileCount - successCount;\r\n const totalBytes = files?.reduce((sum, f) => sum + (f.bytes_read ?? 0), 0) ?? 0;\r\n\r\n const parts: string[] = [\r\n `${fileCount} file${fileCount !== 1 ? 's' : ''}`,\r\n `${successCount} success`,\r\n ];\r\n\r\n if (errorCount > 0) {\r\n parts.push(`${errorCount} error${errorCount !== 1 ? 's' : ''}`);\r\n }\r\n\r\n if (totalBytes > 0) {\r\n parts.push(`${totalBytes} bytes`);\r\n }\r\n\r\n return parts.join(', ');\r\n }\r\n}\r\n", "import type { ToolResult } from '@devicelink-workspace/domain';\r\nimport type { ToolName } from '../executers/types.js';\r\nimport type {\r\n FsListOutput,\r\n FsReadOutput,\r\n FsInfoOutput,\r\n FsTreeOutput,\r\n FsSearchOutput,\r\n FsGrepOutput,\r\n FsReadManyOutput,\r\n} from '@devicelink-workspace/domain';\r\nimport { BaseToolResult } from './base-result.js';\r\nimport { FsListResult } from './fs-list-result.js';\r\nimport { FsReadResult } from './fs-read-result.js';\r\nimport { FsInfoResult } from './fs-info-result.js';\r\nimport { FsTreeResult } from './fs-tree-result.js';\r\nimport { FsSearchResult } from './fs-search-result.js';\r\nimport { FsGrepResult } from './fs-grep-result.js';\r\nimport { FsReadManyResult } from './fs-read-many-result.js';\r\n\r\n/**\r\n * Create a tool result instance based on tool name\r\n */\r\nexport function createToolResult(\r\n toolName: ToolName,\r\n jobId: string,\r\n raw: ToolResult<unknown>,\r\n elapsedSec: number\r\n): BaseToolResult {\r\n switch (toolName) {\r\n case 'fs_list':\r\n return new FsListResult(toolName, jobId, raw as ToolResult<FsListOutput>, elapsedSec);\r\n case 'fs_read':\r\n return new FsReadResult(toolName, jobId, raw as ToolResult<FsReadOutput>, elapsedSec);\r\n case 'fs_info':\r\n return new FsInfoResult(toolName, jobId, raw as ToolResult<FsInfoOutput>, elapsedSec);\r\n case 'fs_tree':\r\n return new FsTreeResult(toolName, jobId, raw as ToolResult<FsTreeOutput>, elapsedSec);\r\n case 'fs_search':\r\n return new FsSearchResult(toolName, jobId, raw as ToolResult<FsSearchOutput>, elapsedSec);\r\n case 'fs_grep':\r\n return new FsGrepResult(toolName, jobId, raw as ToolResult<FsGrepOutput>, elapsedSec);\r\n case 'fs_read_many':\r\n return new FsReadManyResult(toolName, jobId, raw as ToolResult<FsReadManyOutput>, elapsedSec);\r\n default: {\r\n // Fallback to base result for unknown tools\r\n class DefaultToolResult extends BaseToolResult {\r\n protected getDescription(): string {\r\n return this.ok ? 'completed' : 'failed';\r\n }\r\n }\r\n return new DefaultToolResult(toolName, jobId, raw, elapsedSec);\r\n }\r\n }\r\n}\r\n\r\nexport { BaseToolResult } from './base-result.js';\r\nexport { FsListResult } from './fs-list-result.js';\r\nexport { FsReadResult } from './fs-read-result.js';\r\nexport { FsInfoResult } from './fs-info-result.js';\r\nexport { FsTreeResult } from './fs-tree-result.js';\r\nexport { FsSearchResult } from './fs-search-result.js';\r\nexport { FsGrepResult } from './fs-grep-result.js';\r\nexport { FsReadManyResult } from './fs-read-many-result.js';\r\n", "import { WsConnected, WsRx } from \"../../core/events.js\";\nimport { Orchestrator, OrchestratorContext } from \"../../core/orchestrator.js\";\nimport { NotifyScope, NotifyKind } from \"../../core/types.js\";\nimport { BridgeOutboundMsgSchema, ToolResultResponseSchema } from \"@devicelink-workspace/domain\";\nimport type { ToolCallRequest, ToolResult } from \"@devicelink-workspace/domain\";\nimport { ToolExecuterRegistry } from \"./executers\";\nimport type { ToolName, ToolArgs } from \"./executers/types.js\";\nimport { formatToolResultResponse, formatToolErrorResponse, calculateTiming } from \"./utils.js\";\nimport { createToolResult } from \"./results/index.js\";\n\nexport class ToolsOrchestrator implements Orchestrator {\n public readonly name = \"tools-orchestrator\";\n\n public onRegister(_ctx: OrchestratorContext): void {}\n\n public async onStart(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStarted(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public handlers() {\n return {\n \"ws:connected\": async (payload: WsConnected, ctx: OrchestratorContext) => {\n ctx.notifier.info(`WS connected: ${payload.url}`, { scope: NotifyScope.System });\n },\n\n \"ws:rx\": async (payload: WsRx, ctx: OrchestratorContext) => {\n // Parse message to identify tool_call messages\n try {\n const obj = JSON.parse(payload.text);\n const parsed = BridgeOutboundMsgSchema.safeParse(obj);\n if (!parsed.success) {\n ctx.notifier.error('Unexpected message format');\n return;\n }\n\n const msg = parsed.data;\n\n if (parsed.success && parsed.data.type === 'tool_call') {\n // Handle tool_call\n await this.handleToolCall(parsed.data, ctx);\n }\n } catch (e: any) {\n // Not a tool_call or parse failed, ignore\n ctx.notifier.error('Unexpected message format');\n }\n },\n };\n }\n\n private async handleToolCall(call: ToolCallRequest, ctx: OrchestratorContext): Promise<void> {\n const toolName = call.tool as ToolName;\n const jobId = call.job_id;\n const args = call.args ?? {};\n\n // Debug: log args to see if directory_id is present\n const directoryId = args['directory_id'] as string;\n const config = ctx.engine.configurationContext.configuration;\n const availableDirectoryIds = config.directories.map(r => r.id).join(', ') || 'none';\n const availableDirectoryPaths = config.directories.map(r => r.path).join(', ') || 'none';\n ctx.notifier.info(`Tool call: ${toolName} (job=${jobId}, directory_id=${directoryId || 'MISSING'}, available_ids=[${availableDirectoryIds}], available_paths=[${availableDirectoryPaths}], directory_count=${config.directories.length})`, { scope: NotifyScope.System });\n\n // Always-visible tool call notification\n ctx.notifier.info(`Executing: ${toolName}`);\n\n const toolStartTime = Date.now();\n\n try {\n const toolRegistry = new ToolExecuterRegistry(config);\n const raw = await toolRegistry.executeTool(toolName, args as ToolArgs);\n\n const toolResult = formatToolResultResponse(jobId, toolName, raw, toolStartTime);\n\n // Validate with schema\n ToolResultResponseSchema.parse(toolResult);\n\n // Send result back via WebSocket\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolResult) });\n\n // Create result object with toString() for better logging\n const timing = calculateTiming(toolStartTime);\n const result = createToolResult(toolName, jobId, raw, timing.execution_sec);\n\n // Use appropriate notifier based on success/failure\n if (result.ok) {\n ctx.notifier.success(result.toString());\n } else {\n ctx.notifier.error(result.toString());\n }\n } catch (e: unknown) {\n const toolResult = formatToolErrorResponse(jobId, toolName, e, toolStartTime);\n\n // Validate with schema\n ToolResultResponseSchema.parse(toolResult);\n\n // Send error result back via WebSocket\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolResult) });\n\n // Create error result object for consistent logging\n const timing = calculateTiming(toolStartTime);\n const errorResult: ToolResult<unknown> = {\n ok: false,\n error: e instanceof Error ? { code: 'INTERNAL', message: e.message } : { code: 'INTERNAL', message: String(e) },\n };\n const result = createToolResult(toolName, jobId, errorResult, timing.execution_sec);\n ctx.notifier.error(result.toString());\n }\n }\n}\n", "/**\n * Supported tools list - filesystem tools only\n * These are the tools that the agent can execute locally\n */\n\nexport const supportedTools = [\n {\n name: 'fs_list',\n version: '1.0',\n description: 'List files and folders at a relative path inside a shared folder.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n limit: { type: 'integer', minimum: 1, maximum: 1000, default: 200 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n sort: { type: 'string', enum: ['name', 'mtime', 'size'], default: 'name' },\n order: { type: 'string', enum: ['asc', 'desc'], default: 'asc' },\n detail: { type: 'string', enum: ['basic', 'stat', 'digest'], default: 'stat' },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_read',\n version: '1.0',\n description:\n 'Read the contents of a SINGLE text file inside a shared folder. For reading many files at once, prefer fs_read_many instead of multiple fs_read calls.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', minLength: 1 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n limit: { type: 'integer', minimum: 1, maximum: 200000, default: 40000 },\n encoding: { type: 'string', default: 'utf-8' },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_FILE', 'PERMISSION_DENIED', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_info',\n version: '1.0',\n description: 'Get metadata about a file or directory (type, size, timestamps, symlink).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', minLength: 1 },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'PERMISSION_DENIED', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_tree',\n version: '1.0',\n description: 'Return a directory tree from a relative path up to max_depth.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n max_depth: { type: 'integer', minimum: 1, maximum: 20, default: 3 },\n max_entries: { type: 'integer', minimum: 1, maximum: 20000, default: 5000 },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n detail: { type: 'string', enum: ['basic', 'stat', 'digest'], default: 'stat' },\n include_display: { type: 'boolean', default: false },\n max_display_rows: { type: 'integer', minimum: 1, maximum: 20000, default: 2000 },\n },\n required: ['path'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_search',\n version: '1.0',\n description: 'Search for files/folders by name inside a root, optionally recursively.',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n query: { type: 'string', minLength: 1 },\n mode: { type: 'string', enum: ['substring', 'glob'], default: 'substring' },\n recursive: { type: 'boolean', default: true },\n include_hidden: { type: 'boolean', default: false },\n only: { type: 'string', enum: ['all', 'files', 'dirs'], default: 'all' },\n max_results: { type: 'integer', minimum: 1, maximum: 20000, default: 200 },\n },\n required: ['query'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'INVALID_INPUT', 'INTERNAL', 'UNKNOWN_ROOT'],\n },\n {\n name: 'fs_grep',\n version: '1.0',\n description: 'Search for text content inside files (like grep/ripgrep).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n path: { type: 'string', default: '.' },\n query: { type: 'string', minLength: 1 },\n mode: { type: 'string', enum: ['substring', 'regex'], default: 'substring' },\n file_glob: { type: 'string' },\n max_files: { type: 'integer', minimum: 1, maximum: 10000, default: 2000 },\n max_matches: { type: 'integer', minimum: 1, maximum: 1000, default: 200 },\n context_lines: { type: 'integer', minimum: 0, maximum: 10, default: 2 },\n case_sensitive: { type: 'boolean', default: false },\n },\n required: ['query'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_DIRECTORY', 'INVALID_INPUT', 'INTERNAL'],\n },\n {\n name: 'fs_read_many',\n version: '1.0',\n description:\n 'Read multiple files in a single call (batch read). Prefer this over multiple fs_read calls when you need to read several files\u2014fewer round-trips and better performance (up to 50 items per call).',\n inputSchema: {\n type: 'object',\n properties: {\n directory_id: { type: 'string', minLength: 1 },\n items: {\n type: 'array',\n minItems: 1,\n maxItems: 50,\n items: {\n type: 'object',\n properties: {\n path: { type: 'string', minLength: 1 },\n offset: { type: 'integer', minimum: 0, default: 0 },\n limit: { type: 'integer', minimum: 1, maximum: 200000 },\n encoding: { type: 'string' },\n },\n required: ['path'],\n },\n },\n default_limit: { type: 'integer', minimum: 1, maximum: 200000, default: 12000 },\n default_encoding: { type: 'string', default: 'utf-8' },\n },\n required: ['items'],\n },\n errorCodes: ['PATH_ESCAPE', 'NOT_FOUND', 'NOT_A_FILE', 'INVALID_INPUT', 'INTERNAL'],\n },\n] as const;\n", "import { supportedTools } from \"../../../tools/supported-items\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../../../core/job\";\nimport { NotifyScope } from \"../../../core/types\";\nimport type { ToolDef, ToolsPublishRequest } from \"@devicelink-workspace/domain\";\n\n\nexport class SupportedToolsJob extends JobType<void, void> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"tools-job\",\n lane: \"worker\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(_input: void, ctx: JobContext): Promise<void> {\n ctx.notifier.info(`Executing supported tools job`);\n \n const config = ctx.engine.configurationContext.configuration;\n const deviceId = config.device?.id;\n \n if (!deviceId) {\n ctx.notifier.error(`Cannot publish tools: device ID not available`);\n return;\n }\n \n const toolsPublish: ToolsPublishRequest = {\n type: 'tools_publish',\n device_id: deviceId,\n tools: supportedTools as unknown as ToolDef[],\n };\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(toolsPublish) });\n ctx.notifier.success(`\u2192 tools_publish (count=${supportedTools.length})`);\n return;\n }\n}\n\nexport const supportedToolsJob = new SupportedToolsJob();\n\n\nexport function supportedToolsCall(): JobCall<void, void> {\n return new JobCall(supportedToolsJob, void 0);\n}\n", "import { toTildeHomePath } from \"@devicelink-workspace/common\";\nimport { JobCall, JobContext, JobType, JobTypeOptions } from \"../../../core/job\";\nimport { NotifyScope } from \"../../../core/types\";\nimport type { DirectoriesPublishRequest } from \"@devicelink-workspace/domain\";\n\n\nexport class DirectoriesJob extends JobType<void, void> {\n public constructor() {\n super(\n new JobTypeOptions({\n name: \"directories-job\",\n lane: \"worker\",\n priority: 1000,\n locks: [],\n maxAttempts: 1,\n cancellable: false,\n })\n );\n }\n\n public async run(_input: void, ctx: JobContext): Promise<void> {\n ctx.notifier.info(`Executing directories job`);\n \n const config = ctx.engine.configurationContext.configuration;\n const deviceId = config.device?.id;\n \n if (!deviceId) {\n ctx.notifier.error(`Cannot publish directories: device ID not available`);\n return;\n }\n \n const directories = config.directories.map((r) => {\n return {\n id: r.id,\n name: r.name,\n path: toTildeHomePath(r.path) ?? r.name,\n path_hint: r.tag || undefined,\n };\n });\n \n const directoriesPublish: DirectoriesPublishRequest = {\n type: 'directories_publish',\n device_id: deviceId,\n directories,\n };\n ctx.bus.emit(\"ws:tx\", { text: JSON.stringify(directoriesPublish) });\n ctx.notifier.success(`\u2192 directories_publish (dirs=${directoriesPublish.directories.length})`);\n return;\n }\n}\n\nexport const directoriesJob = new DirectoriesJob();\n\n\nexport function directoriesCall(): JobCall<void, void> {\n return new JobCall(directoriesJob, void 0);\n}\n", "import { WsConnected } from \"../../core/events.js\";\nimport { Orchestrator, OrchestratorContext } from \"../../core/orchestrator.js\";\nimport { NotifyScope } from \"../../core/types.js\";\nimport { supportedToolsCall, supportedToolsJob } from \"./jobs/supported-tools.job.js\";\nimport { directoriesCall, directoriesJob } from \"./jobs/directories.job.js\";\n\nexport class MetaDataOrchestrator implements Orchestrator {\n public readonly name = \"meta-data-orchestrator\";\n\n public onRegister(_ctx: OrchestratorContext): void {\n _ctx.engine.register(supportedToolsJob);\n _ctx.engine.register(directoriesJob);\n }\n\n public async onStart(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStarted(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStop(ctx: OrchestratorContext): Promise<void> {\n }\n\n public async onStopped(_ctx: OrchestratorContext): Promise<void> {\n }\n\n public handlers() {\n return {\n \"meta:data:requested:tools\": async (payload: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(`MetaData: tools requested -> dispatching supported tools job`);\n ctx.engine.dispatch(supportedToolsCall());\n },\n \"meta:data:requested:directories\": async (payload: void, ctx: OrchestratorContext) => {\n ctx.notifier.info(`MetaData: directories requested -> dispatching directories job`);\n ctx.engine.dispatch(directoriesCall());\n },\n };\n }\n}\n", "\r\n\r\nexport class ArgvContext {\r\n\r\n public readonly enviromentFile?: string;\r\n public readonly rootPath?: string;\r\n public readonly controlUrl?: string;\r\n public readonly bridgeWsUrl?: string;\r\n public readonly privateKeyFile?: string;\r\n public readonly publicKeyFile?: string;\r\n\r\n constructor(public readonly argv: string[]) {\r\n const trimmedArgv = argv.map(arg => arg.trim()?.toLowerCase());\r\n const originalArgv = argv.map(arg => arg.trim());\r\n const envResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--env']);\r\n if (envResult.match) {\r\n this.enviromentFile = envResult.value;\r\n }\r\n const rootResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--root']);\r\n if (rootResult.match) {\r\n this.rootPath = rootResult.value;\r\n }\r\n const controlUrlResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--control-url']);\r\n if (controlUrlResult.match) {\r\n this.controlUrl = controlUrlResult.value;\r\n }\r\n const bridgeWsUrlResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--bridge-ws-url']);\r\n if (bridgeWsUrlResult.match) {\r\n this.bridgeWsUrl = bridgeWsUrlResult.value;\r\n }\r\n const privateKeyFileResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--private-key-file']);\r\n if (privateKeyFileResult.match && privateKeyFileResult.value) {\r\n this.privateKeyFile = privateKeyFileResult.value;\r\n }\r\n const publicKeyFileResult = this.parseKeyValue(trimmedArgv, originalArgv, ['--public-key-file']);\r\n if (publicKeyFileResult.match && publicKeyFileResult.value) {\r\n this.publicKeyFile = publicKeyFileResult.value;\r\n }\r\n }\r\n\r\n private parseKeyValue(lowerArgv: string[], originalArgv: string[], keys: string[]): {\r\n match: boolean;\r\n value?: string;\r\n } {\r\n const lowerCaseKeys = keys.map(key => key.toLowerCase()?.trim()).filter(key => key !== undefined);\r\n if (lowerCaseKeys.length === 0) {\r\n return { match: false, value: undefined };\r\n }\r\n for (const key of lowerCaseKeys) {\r\n const index = lowerArgv.findIndex(arg => {\r\n const lowerArg = arg.toLowerCase();\r\n // Handle both --key=value and --key formats\r\n return lowerArg === key || lowerArg.startsWith(key + '=');\r\n });\r\n if (index !== -1) {\r\n const originalArg = originalArgv[index]!;\r\n // Check if value is in the same argument (--key=value format)\r\n const equalsIndex = originalArg.toLowerCase().indexOf('=');\r\n if (equalsIndex !== -1) {\r\n const value = originalArg.substring(equalsIndex + 1);\r\n return { match: true, value: value || undefined };\r\n }\r\n // Otherwise, value is in the next argument (--key value format)\r\n return { match: true, value: originalArgv[index + 1] ?? undefined };\r\n }\r\n }\r\n return { match: false, value: undefined };\r\n }\r\n}\r\n", "import { EngineBus } from './eventBus';\nimport { NotifyEvent, NotifyOptions } from './events';\nimport { NotifyKind, NotifyScope, RuntimeFlags } from './types';\n\nexport class Notifier {\n private readonly bus: EngineBus;\n private readonly flags: RuntimeFlags;\n\n public constructor(bus: EngineBus, flags?: RuntimeFlags) {\n this.bus = bus;\n this.flags = flags ?? new RuntimeFlags(false);\n }\n\n public info(\n message: string,\n options?: NotifyOptions,\n ): NotifyEvent | null {\n return this.push(\n message,\n options,\n );\n }\n\n public warn(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Warning });\n return this.push(message, opts);\n }\n\n public error(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Error });\n return this.push(message, opts);\n }\n\n public success(message: string, options?: NotifyOptions): NotifyEvent | null {\n const opts = Object.assign({}, options, { kind: NotifyKind.Success });\n return this.push(message, opts);\n }\n\n private push(\n message: string,\n options?: NotifyOptions,\n ): NotifyEvent | null {\n if (options?.scope === NotifyScope.System && !this.flags.debug) {\n return null;\n }\n\n const entry = new NotifyEvent(message, options);\n this.bus.emit('notify:event', entry);\n return entry;\n }\n}\n", "import { EngineBus } from \"./eventBus\";\nimport { LogEntry, LogOptions } from \"./events\";\nimport { LogLevel } from \"./types\";\n\n\nexport class Logger {\n private readonly bus: EngineBus;\n\n public constructor(bus: EngineBus) {\n this.bus = bus;\n }\n\n public info(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Info }));\n }\n\n public warn(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Warn }));\n }\n\n public error(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Error }));\n }\n\n public debug(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Debug }));\n }\n\n public success(message: string, options?: LogOptions): void {\n this.push(message, Object.assign({}, options, { level: LogLevel.Success }));\n }\n\n private push(message: string, options?: LogOptions): void {\n const entry = new LogEntry(message, options);\n this.bus.emit(\"log\", entry);\n }\n}\n", "#!/usr/bin/env node\nimport { Engine } from \"./core/engine\";\nimport { EventBus } from \"./core/eventBus\";\nimport { MemoryStorage } from \"./core/storage\";\nimport { LaneConfig, RuntimeFlags } from \"./core/types\";\nimport { EngineEventMap } from \"./core/events\";\nimport { createStorage } from \"../storage/index.js\";\n\nimport { loadConfigJob } from \"./jobs/loadConfig\";\nimport { consoleCommandJob } from \"./jobs/consoleCommand\";\nimport { contactServerJob } from \"./jobs/contactServer\";\nimport { sendServerResultJob } from \"./jobs/sendServerResult\";\nimport { refreshTokensJob } from \"./jobs/refreshTokens\";\n\nimport { TelemetryOrchestrator } from \"./orchestrators/telemetry.orchestrator\";\nimport { OSSignalOrchestrator } from \"./orchestrators/os-signal.orchestrator\";\nimport { ConsoleOrchestrator } from \"./orchestrators/console.orchestrator\";\nimport { WebSocketOrchestrator } from \"./orchestrators/socket.orchestrator\";\nimport { MainOrchestrator } from \"./orchestrators/main.orchestrator\";\nimport { AuthOrchestrator } from \"./orchestrators/auth.orchestrator\";\nimport { ToolsOrchestrator } from \"./orchestrators/tools/index.js\";\nimport { MetaDataOrchestrator } from \"./orchestrators/meta-data/index.js\";\nimport { ArgvContext } from \"./core/context\";\nimport { Notifier } from \"./core/notifier\";\nimport { Logger } from \"./core/logger\";\n\nasync function main(): Promise<void> {\n const bus = new EventBus<EngineEventMap>();\n\n const storage = new MemoryStorage();\n const secretStorage = await createStorage();\n const argv = new ArgvContext(process.argv);\n\n const flags = new RuntimeFlags(false);\n const logger = new Logger(bus);\n const notifier = new Notifier(bus, flags);\n\n const engine = new Engine({\n bus,\n argv,\n logger,\n notifier,\n storage,\n secrets: secretStorage,\n flags,\n lanes: [\n new LaneConfig(\"console\", 1),\n new LaneConfig(\"supervisor\", 1),\n new LaneConfig(\"main\", 1),\n new LaneConfig(\"ws\", 1),\n new LaneConfig(\"worker\", 8),\n new LaneConfig(\"io\", 4),\n ],\n });\n\n engine.register(loadConfigJob);\n engine.register(refreshTokensJob);\n engine.register(consoleCommandJob);\n engine.register(contactServerJob);\n engine.register(sendServerResultJob);\n\n engine.registerOrchestrator(new ConsoleOrchestrator());\n engine.registerOrchestrator(new TelemetryOrchestrator(\"./engine_state/telemetry.ndjson\"));\n engine.registerOrchestrator(new OSSignalOrchestrator());\n engine.registerOrchestrator(new MainOrchestrator());\n engine.registerOrchestrator(new AuthOrchestrator());\n engine.registerOrchestrator(new WebSocketOrchestrator());\n engine.registerOrchestrator(new ToolsOrchestrator());\n engine.registerOrchestrator(new MetaDataOrchestrator());\n\n await engine.init();\n\n await engine.start();\n}\n\nvoid main();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["crypto", "resolve", "path", "os", "fs", "get", "isEmpty", "require", "crypto", "crypto", "crypto", "path", "crypto", "resolve", "path", "os", "path", "path", "fs", "os", "isEmpty", "get", "directory", "Engine", "resolve", "crypto", "crypto", "fs", "path", "os", "defaultTo", "ok", "ok", "resolve", "ok", "resolve", "ok", "resolve", "crypto", "path", "ok", "crypto", "React", "useEffect", "Box", "React", "useEffect", "useState", "useEffect", "useState", "useState", "useEffect", "jsx", "useState", "useEffect", "deviceIdDisplay", "React", "React", "useMemo", "Box", "Text", "jsx", "jsxs", "React", "LogPane", "useMemo", "Box", "Text", "LogRow", "React", "Box", "Text", "jsx", "jsxs", "React", "InputBar", "Box", "Text", "Box", "Text", "Fragment", "jsx", "jsxs", "jsx", "jsxs", "useEffect", "Box", "React", "handler", "resolve", "ws", "fs", "path", "os", "defaultTo", "crypto", "z", "z", "DeviceAuthStreamResponseSchema", "ok", "crypto", "output", "delayMs", "sec", "fs", "path", "path", "fs", "fs", "path", "fs", "context", "path", "fs", "fs", "fs", "fs", "fs", "path", "fs", "path", "fs", "path", "isEmpty", "isEmpty", "toolError", "fs", "toolError", "node", "path", "fs", "path", "matchesGlob", "matchesFileGlob", "fs", "path", "isObject", "get", "ok", "path", "path", "path", "path", "path", "path", "Engine"]
|
|
7
7
|
}
|