lody 0.105.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/baguette-worker.js +1 -1
- package/dist/chunks/{cloudflared-native-CT-eRa_M.js → cloudflared-native-CJVH1-0P.js} +2 -2
- package/dist/chunks/{daemon-session-tools-DtsKbbQ9.js → daemon-session-tools-Bgq2Cj2S.js} +6 -6
- package/dist/chunks/{diff-line-counts-Cr-lqn_D.js → diff-line-counts-D6bAVmNB.js} +2 -2
- package/dist/chunks/{diff-worker-task-BuDrFtkp.js → diff-worker-task-rnxgvZHM.js} +2 -2
- package/dist/chunks/{directory-handle-BNSLkXDU.js → directory-handle-DssOMLsI.js} +3 -3
- package/dist/chunks/{index-CtXoAGVz.js → index-DnWlNrUf.js} +2 -2
- package/dist/chunks/{index-CU8Ghgdl.js → index-a0nEYQPa.js} +6 -6
- package/dist/chunks/{process-22-gqNSA.js → process-DZ2dHvHL.js} +91 -17
- package/dist/chunks/{review-viewer-DS24MU0Q.js → review-viewer-Cm1OZZZc.js} +4 -4
- package/dist/cloudflared-worker.js +2 -2
- package/dist/diff-worker.js +3 -3
- package/dist/file-index-scan-worker.js +3 -3
- package/dist/index.js +392 -144
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,13 +6,13 @@ import fs__default$1, { createReadStream, existsSync, realpathSync, statSync, cr
|
|
|
6
6
|
import * as readline$1 from "node:readline";
|
|
7
7
|
import readline__default, { createInterface } from "node:readline";
|
|
8
8
|
import require$$5$3, { AsyncLocalStorage, AsyncResource } from "node:async_hooks";
|
|
9
|
-
import { g as getLodyDataDir, r as resolvePlatformKind, a as requireMs, b as getLogger, f as formatSafeLogFields, L as LODY_LOG_DIR, c as rootLogger, t as toShared, d as LOCAL_USER_ID_PREFIX, e as LOCAL_WORKSPACE_ID_PREFIX, h as formatErrorMessage, i as getInstallationProfile, j as registerLoroSyncErrorFormatter, l as listDailyLogFiles, k as readDailyLogFile, m as formatErrorWithCauses, n as truncateLogText, w as withSpawn, p as platformLayer, o as LodyDataDirUnavailableError, q as ensureLodyDataDir, C as CloudflaredError, u as routeLoggerToStderr, v as createHybridLogger, x as readLatestLogTail, y as createFileLogger } from "./chunks/cloudflared-native-
|
|
9
|
+
import { g as getLodyDataDir, r as resolvePlatformKind, a as requireMs, b as getLogger, f as formatSafeLogFields, L as LODY_LOG_DIR, c as rootLogger, t as toShared, d as LOCAL_USER_ID_PREFIX, e as LOCAL_WORKSPACE_ID_PREFIX, h as formatErrorMessage, i as getInstallationProfile, j as registerLoroSyncErrorFormatter, l as listDailyLogFiles, k as readDailyLogFile, m as formatErrorWithCauses, n as truncateLogText, w as withSpawn, p as platformLayer, o as LodyDataDirUnavailableError, q as ensureLodyDataDir, C as CloudflaredError, u as routeLoggerToStderr, v as createHybridLogger, x as readLatestLogTail, y as createFileLogger } from "./chunks/cloudflared-native-CJVH1-0P.js";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import fs__default, { promises, readFileSync, writeFileSync, mkdirSync as mkdirSync$1, lstatSync as lstatSync$1, unlinkSync, realpathSync as realpathSync$1, statSync as statSync$1, accessSync as accessSync$1, constants as constants$8, existsSync as existsSync$1 } from "fs";
|
|
12
12
|
import * as crypto$4 from "crypto";
|
|
13
13
|
import crypto__default, { randomUUID as randomUUID$1, createHash as createHash$1, randomBytes as randomBytes$4, webcrypto, createHmac, createSign, createCipheriv, createDecipheriv, timingSafeEqual as timingSafeEqual$1 } from "crypto";
|
|
14
14
|
import { j as _coercedNumber, Z as ZodNumber, o as object, s as string$4, l as literal, d as discriminatedUnion, _ as _enum, a as array$1, n as number$3, b as boolean$1, r as record$5, c as unknown$1, p as preprocess$1, u as union$1, g as _null, k as custom, m as ZodObject, q as ZodLiteral, v as json, w as ZodError, x as safeParse, y as ZodOptional, z as ZodNullable, A as ZodPipe, B as ZodUnion, C as ZodArray, D as ZodNever, E as ZodDiscriminatedUnion, F as _instanceof, G as uuid, N as NEVER, H as lazy, h as looseObject, e as intersection, I as optional$2, J as datetime, f as url, K as any, L as toJSONSchema, M as date, O as email, P as xor, Q as never$2 } from "./chunks/schemas-Bue2bhN8.js";
|
|
15
|
-
import { T as Tuple, y as dual, z as assignProperty, A as none, B as some, D as identity$2, E as hash$1, F as symbol, G as pipe$2, H as isNone, I as equals, J as symbol$1, K as optimize, N as NodeInspectSymbol, L as toJson, O as format$2, P as pipeArguments, Q as hasProperty, R as string$5, S as backEdges, U as combine$1, V as BaseProto, W as seconds, X as PipeInspectableProto, Y as isString$1, Z as structure, _ as redact$1, $ as symbolRedactable, a0 as get$2, a1 as Reference, a2 as strictEqual, a3 as fromIterable$1, a4 as array$2, a5 as make$c, a6 as makeEquivalence$2, a7 as memoize, a8 as succeed$1, a9 as isReadonlyArrayNonEmpty, aa as map$2, ab as formatPath, ac as isFailReason, ad as Prototype, ae as Class, af as resolveConcurrency, ag as fail, ah as effectIsExit, ai as die$1, aj as iterateConcurrent, ak as fnUntracedEager, al as flatMap$1, am as exit$1, an as flatMapEager, ao as void_, ap as args$1, aq as fail$1, ar as append, as as iterateEager, at as failCause, au as map$3, av as memoizeIdempotent, aw as isFunction$2, ax as isPropertyKey, ay as isNotNullish, az as empty$7, aA as isArrayNonEmpty, aB as formatPropertyKey, aC as suspend, aD as isObjectKeyword, aE as catchCause, aF as succeed$2, aG as isUnknown, aH as isNumber$1, aI as isBoolean, aJ as mapEager, aK as failCauseSync, aL as isSuccess, aM as runSyncExit, aN as die$2, aO as succeed$3, aP as fail$2, aQ as mapError, aR as TaggedError, aS as setStackTraceLimit, aT as getStackTraceLimit, aU as Service, aV as try_, aW as badArgument, aX as unwrap$1, aY as map$4, aZ as forEach, a_ as fnUntraced, a$ as unwrap$2, b0 as fromPull, b1 as done, b2 as match$1, b3 as of$1, b4 as catchTag, b5 as as, b6 as forkUnsafe, b7 as runIn, b8 as makeUnsafe, b as runPromise, b9 as runPromiseWith, ba as runPromiseExit, bb as runPromiseExitWith, bc as runSync$1, bd as runSyncWith, be as runSyncExitWith, bf as runCallback, bg as runCallbackWith, bh as runFork, bi as runForkWith, bj as withFiber, bk as scopeRemoveFinalizerUnsafe, bl as close, bm as tap$1, bn as buildWithMemoMap, bo as sync, bp as flatten, bq as await_, br as makeMemoMapUnsafe, bs as provideContext, bt as gen, bu as forEach$1, bv as ensuring, bw as isFailure, bx as failCause$1, by as combine$2, bz as callback, bA as void_$1, bB as fail$3, bC as raceFirst, bD as interruptible, d as sleep$5, bE as andThen, bF as make$d, bG as make$e, bH as hasInterruptsOnly, bI as hasDies, bJ as uninterruptibleMask, bK as forkIn, bL as join, bM as timeout$1, bN as uninterruptible, bO as die$3, bP as done$1, bQ as _await, bR as makeUnsafe$1, bS as isDoneUnsafe, bT as addFinalizer, bU as tapCause, i as effect, bV as isInterruptReason, bW as isDieReason, bX as isCause, bY as isTimeoutError, bZ as provide$1, b_ as pretty, b$ as catch_, c0 as currentTimeMillis, c1 as sync$1, o as getDefaultExportFromCjs, c2 as makeUnsafe$2, c3 as modify$1, c4 as set$4, c5 as getUnsafe, c6 as fork, c7 as scope, c8 as make$f, c9 as get$3, ca as make$g, cb as interrupt, cc as ProcessReleaseFailed, cd as squash, ce as timeoutOrElse, cf as asVoid, cg as provideMerge, q as merge$3, g as processLayer, ch as ChildProcessSpawner, ci as toMillis, cj as CommandTimedOut, ck as runCommandOk, cl as READ_ONLY_ABANDON_POLICY, cm as provideService, cn as findErrorOption, co as isSome, cp as CommandFailed, cq as SpawnFailed, cr as errnoCode, v as succeed$4, cs as squashProcessFailure, ct as try_$1, cu as fromNullishOr, cv as getOrUndefined, cw as isSuccess$1, cx as Class$1, cy as fromReadableStream, cz as fail$4, cA as tryPromise, cB as cached, cC as constFalse, cD as isFailure$1, cE as DisablePropagation, cF as matchCauseEffect, cG as hasInterrupts, cH as useSpan, cI as withParentSpan, cJ as TracerTimingEnabled, cK as Clock, cL as constTrue, cM as onInterrupt, cN as suspend$1, cO as ensuring$1, cP as interrupt$1, cQ as fail$5, cR as mapError$1, cS as never$1, cT as yieldNow, cU as doneUnsafe, cV as forkDetach, cW as orDie, p as promise, cX as empty$8, cY as logDebug, e as provide$2, cZ as provide$3, c_ as Scope, c$ as context, d0 as timeoutOption, d1 as TimeoutError$3, d2 as forever, d3 as unbounded, d4 as offerUnsafe, d5 as take$1, n as commonjsGlobal, m as getAugmentedNamespace, d6 as fromReasons, s as startProcessLegacy, d7 as systemError, d8 as serviceOption, d9 as acquireRelease, da as flatMap$2, db as getOrElse, dc as effectify, dd as callback$1, de as matchEffect, df as offer, dg as failCauseUnsafe, dh as endUnsafe, di as mergeAll$1, dj as NodeProcess, x as nodeProcessLive, dk as probePid, dl as update, dm as acquireUseRelease, dn as toStepWithMetadata, dp as forever$1, dq as modifyDelay, dr as getAndUpdate, ds as match$2, dt as make$h, du as shutdown, dv as makeDieReason, dw as makeUnsafe$3, r as runCommandTextLegacy, dx as all$1, f as runCommand$1, dy as result, dz as isPidAliveSyncLegacy, t as terminateChildTreeLegacy, dA as scoped, dB as ProcessCleanupFailed, dC as runPromiseSquashedLegacy, dD as fn, dE as tap$2, dF as map$5, dG as filter$1, dH as runHead, dI as getOrThrow, dJ as tapError, dK as spawn, dL as terminateTree, dM as succeed$5, dN as exists$1, dO as logWarning, dP as spawnProcess, dQ as TerminationFailed, dR as makeProcessRunnerLegacy, dS as unwrapSpawnFailure, a as runCommandTextSyncLegacy, dT as addFinalizer$1, dU as repeat$1, dV as spaced, dW as delay$4, dX as min$1, dY as exponential, dZ as minutes, d_ as jittered, d$ as while_, e0 as retry$2, e1 as takeBetween, e2 as forkScoped, e3 as unwrap$3, e4 as dropping, e5 as makeUnsafe$4, e6 as CommandOutputTooLarge, e7 as isEffect, e8 as take$2, e9 as release$1, ea as withPermits, eb as posixGroupTree, ec as waitUntilGone, ed as Effect, ee as childProcessTree, ef as hasExited, eg as isDone } from "./chunks/process-
|
|
15
|
+
import { T as Tuple, y as dual, z as assignProperty, A as none, B as some, D as identity$2, E as hash$1, F as symbol, G as pipe$2, H as isNone, I as equals, J as symbol$1, K as optimize, N as NodeInspectSymbol, L as toJson, O as format$2, P as pipeArguments, Q as hasProperty, R as string$5, S as backEdges, U as combine$1, V as BaseProto, W as seconds, X as PipeInspectableProto, Y as isString$1, Z as structure, _ as redact$1, $ as symbolRedactable, a0 as get$2, a1 as Reference, a2 as strictEqual, a3 as fromIterable$1, a4 as array$2, a5 as make$c, a6 as makeEquivalence$2, a7 as memoize, a8 as succeed$1, a9 as isReadonlyArrayNonEmpty, aa as map$2, ab as formatPath, ac as isFailReason, ad as Prototype, ae as Class, af as resolveConcurrency, ag as fail, ah as effectIsExit, ai as die$1, aj as iterateConcurrent, ak as fnUntracedEager, al as flatMap$1, am as exit$1, an as flatMapEager, ao as void_, ap as args$1, aq as fail$1, ar as append, as as iterateEager, at as failCause, au as map$3, av as memoizeIdempotent, aw as isFunction$2, ax as isPropertyKey, ay as isNotNullish, az as empty$7, aA as isArrayNonEmpty, aB as formatPropertyKey, aC as suspend, aD as isObjectKeyword, aE as catchCause, aF as succeed$2, aG as isUnknown, aH as isNumber$1, aI as isBoolean, aJ as mapEager, aK as failCauseSync, aL as isSuccess, aM as runSyncExit, aN as die$2, aO as succeed$3, aP as fail$2, aQ as mapError, aR as TaggedError, aS as setStackTraceLimit, aT as getStackTraceLimit, aU as Service, aV as try_, aW as badArgument, aX as unwrap$1, aY as map$4, aZ as forEach, a_ as fnUntraced, a$ as unwrap$2, b0 as fromPull, b1 as done, b2 as match$1, b3 as of$1, b4 as catchTag, b5 as as, b6 as forkUnsafe, b7 as runIn, b8 as makeUnsafe, b as runPromise, b9 as runPromiseWith, ba as runPromiseExit, bb as runPromiseExitWith, bc as runSync$1, bd as runSyncWith, be as runSyncExitWith, bf as runCallback, bg as runCallbackWith, bh as runFork, bi as runForkWith, bj as withFiber, bk as scopeRemoveFinalizerUnsafe, bl as close, bm as tap$1, bn as buildWithMemoMap, bo as sync, bp as flatten, bq as await_, br as makeMemoMapUnsafe, bs as provideContext, bt as gen, bu as forEach$1, bv as ensuring, bw as isFailure, bx as failCause$1, by as combine$2, bz as callback, bA as void_$1, bB as fail$3, bC as raceFirst, bD as interruptible, d as sleep$5, bE as andThen, bF as make$d, bG as make$e, bH as hasInterruptsOnly, bI as hasDies, bJ as uninterruptibleMask, bK as forkIn, bL as join, bM as timeout$1, bN as uninterruptible, bO as die$3, bP as done$1, bQ as _await, bR as makeUnsafe$1, bS as isDoneUnsafe, bT as addFinalizer, bU as tapCause, i as effect, bV as isInterruptReason, bW as isDieReason, bX as isCause, bY as isTimeoutError, bZ as provide$1, b_ as pretty, b$ as catch_, c0 as currentTimeMillis, c1 as sync$1, o as getDefaultExportFromCjs, c2 as makeUnsafe$2, c3 as modify$1, c4 as set$4, c5 as getUnsafe, c6 as fork, c7 as scope, c8 as make$f, c9 as get$3, ca as make$g, cb as interrupt, cc as ProcessReleaseFailed, cd as squash, ce as timeoutOrElse, cf as asVoid, cg as provideMerge, q as merge$3, g as processLayer, ch as ChildProcessSpawner, ci as toMillis, cj as CommandTimedOut, ck as runCommandOk, cl as READ_ONLY_ABANDON_POLICY, cm as provideService, cn as findErrorOption, co as isSome, cp as CommandFailed, cq as SpawnFailed, cr as errnoCode, v as succeed$4, cs as squashProcessFailure, ct as try_$1, cu as fromNullishOr, cv as getOrUndefined, cw as isSuccess$1, cx as Class$1, cy as fromReadableStream, cz as fail$4, cA as tryPromise, cB as cached, cC as constFalse, cD as isFailure$1, cE as DisablePropagation, cF as matchCauseEffect, cG as hasInterrupts, cH as useSpan, cI as withParentSpan, cJ as TracerTimingEnabled, cK as Clock, cL as constTrue, cM as onInterrupt, cN as suspend$1, cO as ensuring$1, cP as interrupt$1, cQ as fail$5, cR as mapError$1, cS as never$1, cT as yieldNow, cU as doneUnsafe, cV as forkDetach, cW as orDie, p as promise, cX as empty$8, cY as logDebug, e as provide$2, cZ as provide$3, c_ as Scope, c$ as context, d0 as timeoutOption, d1 as TimeoutError$3, d2 as forever, d3 as unbounded, d4 as offerUnsafe, d5 as take$1, n as commonjsGlobal, m as getAugmentedNamespace, d6 as fromReasons, s as startProcessLegacy, d7 as systemError, d8 as serviceOption, d9 as acquireRelease, da as flatMap$2, db as getOrElse, dc as effectify, dd as callback$1, de as matchEffect, df as offer, dg as failCauseUnsafe, dh as endUnsafe, di as mergeAll$1, dj as NodeProcess, x as nodeProcessLive, dk as probePid, dl as update, dm as acquireUseRelease, dn as toStepWithMetadata, dp as forever$1, dq as modifyDelay, dr as getAndUpdate, ds as match$2, dt as make$h, du as shutdown, dv as makeDieReason, dw as makeUnsafe$3, r as runCommandTextLegacy, dx as all$1, f as runCommand$1, dy as result, dz as isPidAliveSyncLegacy, t as terminateChildTreeLegacy, dA as scoped, dB as ProcessCleanupFailed, dC as runPromiseSquashedLegacy, dD as fn, dE as tap$2, dF as map$5, dG as filter$1, dH as runHead, dI as getOrThrow, dJ as tapError, dK as spawn, dL as terminateTree, dM as succeed$5, dN as exists$1, dO as logWarning, dP as spawnProcess, dQ as TerminationFailed, dR as makeProcessRunnerLegacy, dS as unwrapSpawnFailure, a as runCommandTextSyncLegacy, dT as addFinalizer$1, dU as repeat$1, dV as spaced, dW as delay$4, dX as min$1, dY as exponential, dZ as minutes, d_ as jittered, d$ as while_, e0 as retry$2, e1 as takeBetween, e2 as forkScoped, e3 as unwrap$3, e4 as dropping, e5 as makeUnsafe$4, e6 as CommandOutputTooLarge, e7 as isEffect, e8 as take$2, e9 as release$1, ea as withPermits, eb as posixGroupTree, ec as waitUntilGone, ed as Effect, ee as childProcessTree, ef as hasExited, eg as isDone } from "./chunks/process-DZ2dHvHL.js";
|
|
16
16
|
import require$$0$3, { once, EventEmitter as EventEmitter$1 } from "node:events";
|
|
17
17
|
import NodeChildProcess, { execFileSync } from "node:child_process";
|
|
18
18
|
import * as path from "node:path";
|
|
@@ -63,7 +63,7 @@ import * as fs$3 from "node:fs/promises";
|
|
|
63
63
|
import fs__default$3, { realpath, mkdir as mkdir$1, writeFile as writeFile$1, rename as rename$1, rm, symlink as symlink$1, mkdtemp, chmod as chmod$1, readFile as readFile$1, readdir, stat as stat$2, lstat, unlink, open as open$1, opendir, link as link$1 } from "node:fs/promises";
|
|
64
64
|
import { a as parseWorkspaceWatchChildMessage, C as CODE_COLLAB_IGNORED_DIRECTORY_NAMES } from "./chunks/workspace-watch-path-policy-BRzhvEkG.js";
|
|
65
65
|
import { StringDecoder } from "node:string_decoder";
|
|
66
|
-
import { C as CodeCollabV2FileIndexRequestSchema, d as CodeCollabV2OpenTextRequestSchema, e as CodeCollabV2RefreshTextRequestSchema, f as CodeCollabV2SaveTextRequestSchema, g as CodeCollabV2OpenCurrentDiffRequestSchema, h as CodeCollabV2OpenAllChangesDiffRequestSchema, k as CodeCollabV2OpenTurnDiffRequestSchema, l as CodeCollabV2InitDirectoryRequestSchema, m as CodeCollabV2FileIndexSnapshotSchema, n as CodeCollabV2OpenTextOkSchema, o as CodeCollabV2RefreshTextResponseSchema, q as CodeCollabV2SaveTextResponseSchema, r as CodeCollabV2OpenCurrentDiffResponseSchema, t as CodeCollabV2OpenAllChangesDiffResponseSchema, u as CodeCollabV2OpenTurnDiffResponseSchema, v as CodeCollabV2InitDirectoryOkSchema, w as CodeCollabV2LspUnsupportedSchema, x as CodeCollabV2ErrorSchema, y as CodeCollabV2RpcContentEnvelopeSchema, z as deriveCodeCollabV2ContentKeyId, A as CodeCollabV2ErrorCodeSchema, B as CodeCollabV2RpcResponseSchema, D as deriveCodeCollabV2ContentKeyBytes, E as readCodeCollabFileIndexSignalFromFlock, F as writeCodeCollabFileIndexSignalToFlock, G as writeCodeCollabFileIndexToFlock, H as gitDiffBaseRefCandidates, b as buildCodeCollabFileIndexState, I as CODE_COLLAB_V2_TEXT_LIMITS, J as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, K as resolveAllChangesDiffBase, c as computeAllChanges, L as codeCollabFileIndexStatesEqual, s as scanGitDirectoryEntries, a as closeDirectoryQuietly } from "./chunks/directory-handle-
|
|
66
|
+
import { C as CodeCollabV2FileIndexRequestSchema, d as CodeCollabV2OpenTextRequestSchema, e as CodeCollabV2RefreshTextRequestSchema, f as CodeCollabV2SaveTextRequestSchema, g as CodeCollabV2OpenCurrentDiffRequestSchema, h as CodeCollabV2OpenAllChangesDiffRequestSchema, k as CodeCollabV2OpenTurnDiffRequestSchema, l as CodeCollabV2InitDirectoryRequestSchema, m as CodeCollabV2FileIndexSnapshotSchema, n as CodeCollabV2OpenTextOkSchema, o as CodeCollabV2RefreshTextResponseSchema, q as CodeCollabV2SaveTextResponseSchema, r as CodeCollabV2OpenCurrentDiffResponseSchema, t as CodeCollabV2OpenAllChangesDiffResponseSchema, u as CodeCollabV2OpenTurnDiffResponseSchema, v as CodeCollabV2InitDirectoryOkSchema, w as CodeCollabV2LspUnsupportedSchema, x as CodeCollabV2ErrorSchema, y as CodeCollabV2RpcContentEnvelopeSchema, z as deriveCodeCollabV2ContentKeyId, A as CodeCollabV2ErrorCodeSchema, B as CodeCollabV2RpcResponseSchema, D as deriveCodeCollabV2ContentKeyBytes, E as readCodeCollabFileIndexSignalFromFlock, F as writeCodeCollabFileIndexSignalToFlock, G as writeCodeCollabFileIndexToFlock, H as gitDiffBaseRefCandidates, b as buildCodeCollabFileIndexState, I as CODE_COLLAB_V2_TEXT_LIMITS, J as CODE_COLLAB_V2_ALL_CHANGES_DIFF_LIMITS, K as resolveAllChangesDiffBase, c as computeAllChanges, L as codeCollabFileIndexStatesEqual, s as scanGitDirectoryEntries, a as closeDirectoryQuietly } from "./chunks/directory-handle-DssOMLsI.js";
|
|
67
67
|
import { performance as performance$1 } from "perf_hooks";
|
|
68
68
|
import require$$0$e, { EventEmitter as EventEmitter$2 } from "events";
|
|
69
69
|
import require$$0$d, { Transform as Transform$1, Readable as Readable$1 } from "stream";
|
|
@@ -81,8 +81,8 @@ import { setTimeout as setTimeout$1 } from "timers/promises";
|
|
|
81
81
|
import * as timers$2 from "node:timers/promises";
|
|
82
82
|
import { setTimeout as setTimeout$2 } from "node:timers/promises";
|
|
83
83
|
import { RoostHostError, RoostNativeClient } from "@loro-dev/roost-node";
|
|
84
|
-
import { c as computeLineCounts, a as countTextLines } from "./chunks/diff-line-counts-
|
|
85
|
-
import { r as runDiffWorkerTask } from "./chunks/diff-worker-task-
|
|
84
|
+
import { c as computeLineCounts, a as countTextLines } from "./chunks/diff-line-counts-D6bAVmNB.js";
|
|
85
|
+
import { r as runDiffWorkerTask } from "./chunks/diff-worker-task-rnxgvZHM.js";
|
|
86
86
|
import { createRequire as createRequire$1 } from "node:module";
|
|
87
87
|
import v8 from "node:v8";
|
|
88
88
|
import require$$0$f from "child_process";
|
|
@@ -4315,7 +4315,7 @@ class PostHog extends PostHogBackendClient {
|
|
|
4315
4315
|
}
|
|
4316
4316
|
const name$3 = "lody";
|
|
4317
4317
|
const name$2 = "@lody/cli-cloud";
|
|
4318
|
-
const version$g = "0.
|
|
4318
|
+
const version$g = "0.106.0";
|
|
4319
4319
|
const type = "module";
|
|
4320
4320
|
const scripts = { "dev": "node dev.mjs", "dev:staging": "LODY_ENV=staging NODE_ENV=production node dev.mjs", "build": "node build.mjs", "prepare:publish": "node prepare-publish.js", "test": "node --test pnpm-runner.test.mjs vite-config.test.mjs nightly-npm.test.mjs" };
|
|
4321
4321
|
const devDependencies = { "dotenv": "^16.6.1", "vite": "^7.0.0", "vite-plugin-wasm": "catalog:" };
|
|
@@ -116452,6 +116452,94 @@ const redactUrlAuth = (raw2) => {
|
|
|
116452
116452
|
return raw2;
|
|
116453
116453
|
}
|
|
116454
116454
|
};
|
|
116455
|
+
const GITHUB_TOKEN_CLOUD_TIMEOUT_MS = 15e3;
|
|
116456
|
+
const GITHUB_BROKER_TOKEN_TIMEOUT_MS = GITHUB_TOKEN_CLOUD_TIMEOUT_MS + 5e3;
|
|
116457
|
+
const githubCredentialRuntime = String.raw`
|
|
116458
|
+
const credentialError = (code, details = {}) => Object.assign(new Error(code), { code, ...details });
|
|
116459
|
+
const errorCode = error => {
|
|
116460
|
+
if (error?.name === 'TimeoutError' || error?.name === 'AbortError') return 'timeout';
|
|
116461
|
+
const code = [error?.code, error?.cause?.code].find(value => typeof value === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(value));
|
|
116462
|
+
return typeof code === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(code) ? code : 'unexpected_error';
|
|
116463
|
+
};
|
|
116464
|
+
const diagnostic = (source, stage, error) => {
|
|
116465
|
+
const detail = { source, stage, code: errorCode(error) };
|
|
116466
|
+
if (Number.isInteger(error?.status)) detail.status = error.status;
|
|
116467
|
+
if (typeof error?.requestId === 'string' && /^[a-f0-9-]{1,64}$/.test(error.requestId)) detail.requestId = error.requestId;
|
|
116468
|
+
console.error('[Lody GitHub] ' + JSON.stringify(detail));
|
|
116469
|
+
return detail;
|
|
116470
|
+
};
|
|
116471
|
+
// This file is authored by the host, never inferred from a child's token/env.
|
|
116472
|
+
// A pinned context token names an immutable snapshot for host-side clone/fetch.
|
|
116473
|
+
const readCredentialContext = (fs, statePath, env) => {
|
|
116474
|
+
const file = env.LODY_GIT_CRED_CONTEXT_FILE || (env.LODY_GIT_CRED_CONTEXT_TOKEN && statePath + '.contexts/' + env.LODY_GIT_CRED_CONTEXT_TOKEN + '.json');
|
|
116475
|
+
if (!file) throw credentialError('context_missing');
|
|
116476
|
+
let context;
|
|
116477
|
+
try { context = JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
116478
|
+
catch (cause) { throw credentialError('context_unreadable', { cause }); }
|
|
116479
|
+
if (context?.version !== 1 || typeof context.contextToken !== 'string' || !context.contextToken || typeof context.allowLocalAuth !== 'boolean') throw credentialError('context_invalid');
|
|
116480
|
+
return context;
|
|
116481
|
+
};
|
|
116482
|
+
const readCredentialPolicy = () => {
|
|
116483
|
+
const context = getContext();
|
|
116484
|
+
return { allowLocalAuth: context.allowLocalAuth, personalEnabled: true };
|
|
116485
|
+
};
|
|
116486
|
+
const readManagedCandidate = async (repoFullName, source) => {
|
|
116487
|
+
const response = await requestBroker('/github-token', {
|
|
116488
|
+
repoFullName, source, contextToken: getContext().contextToken,
|
|
116489
|
+
}, ${GITHUB_BROKER_TOKEN_TIMEOUT_MS});
|
|
116490
|
+
if (!response) throw credentialError('broker_unavailable');
|
|
116491
|
+
let body;
|
|
116492
|
+
try { body = await response.json(); }
|
|
116493
|
+
catch (cause) { throw credentialError(errorCode(cause) === 'timeout' ? 'timeout' : 'invalid_response', { cause, status: response.status }); }
|
|
116494
|
+
if (!response.ok) throw credentialError(typeof body.error === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(body.error) ? body.error : 'broker_http_error', { status: response.status, requestId: body.requestId });
|
|
116495
|
+
if (body.available === false) throw credentialError(typeof body.reason === 'string' && /^[a-z_]{1,64}$/.test(body.reason) ? body.reason : 'credential_unavailable');
|
|
116496
|
+
if (typeof body.token !== 'string' || !body.token || /[\r\n]/.test(body.token) || body.tokenSource !== source) throw credentialError('invalid_credential_response');
|
|
116497
|
+
return { token: body.token };
|
|
116498
|
+
};
|
|
116499
|
+
// One acquisition per source. Consumers can continue after a provably safe
|
|
116500
|
+
// failure of the actual operation; never restart this iterator to retry a source.
|
|
116501
|
+
async function* githubCredentials(repo, policy, localCandidate, anonymous = false) {
|
|
116502
|
+
const failures = [];
|
|
116503
|
+
for (const source of ['personal', 'local', 'app', ...(anonymous ? ['anonymous'] : [])]) {
|
|
116504
|
+
if (source === 'personal' && policy.personalEnabled === false) continue;
|
|
116505
|
+
if (source === 'local' && !policy.allowLocalAuth) continue;
|
|
116506
|
+
try {
|
|
116507
|
+
const candidate = source === 'anonymous' ? { token: null } : source === 'local' ? await localCandidate() : await readManagedCandidate(repo, source);
|
|
116508
|
+
if (!candidate) throw credentialError('credential_missing');
|
|
116509
|
+
yield { ...candidate, source };
|
|
116510
|
+
} catch (error) {
|
|
116511
|
+
failures.push(diagnostic(source, 'acquire', error));
|
|
116512
|
+
}
|
|
116513
|
+
}
|
|
116514
|
+
throw credentialError('credentials_exhausted', { failures });
|
|
116515
|
+
}
|
|
116516
|
+
const selectGitHubCredential = async (repo, policy, localCandidate, requireWrite, anonymousCandidate, verify = async () => true) => {
|
|
116517
|
+
const failures = [];
|
|
116518
|
+
try {
|
|
116519
|
+
for await (const candidate of githubCredentials(repo, policy, localCandidate, !requireWrite && !!anonymousCandidate)) {
|
|
116520
|
+
try {
|
|
116521
|
+
if (candidate.source === 'anonymous' && !await anonymousCandidate()) throw credentialError('anonymous_unavailable');
|
|
116522
|
+
if (!await verify(candidate)) throw credentialError('access_denied');
|
|
116523
|
+
console.error('[Lody GitHub] ' + JSON.stringify({ source: candidate.source, stage: 'selected', repo }));
|
|
116524
|
+
return candidate;
|
|
116525
|
+
} catch (error) { failures.push(diagnostic(candidate.source, 'access', error)); }
|
|
116526
|
+
}
|
|
116527
|
+
} catch (error) {
|
|
116528
|
+
if (error.code === 'credentials_exhausted') error.failures.push(...failures);
|
|
116529
|
+
throw error;
|
|
116530
|
+
}
|
|
116531
|
+
};
|
|
116532
|
+
`;
|
|
116533
|
+
const withRequestDeadline = (timeoutMs, fetchImpl = fetch) => (input2, init2) => {
|
|
116534
|
+
const deadline = new AbortController();
|
|
116535
|
+
const timer2 = setTimeout(
|
|
116536
|
+
() => deadline.abort(new DOMException("GitHub token request timed out", "TimeoutError")),
|
|
116537
|
+
timeoutMs
|
|
116538
|
+
);
|
|
116539
|
+
timer2.unref?.();
|
|
116540
|
+
const signal = init2?.signal ? AbortSignal.any([init2.signal, deadline.signal]) : deadline.signal;
|
|
116541
|
+
return fetchImpl(input2, { ...init2, signal });
|
|
116542
|
+
};
|
|
116455
116543
|
const GitHubTokenSuccessSchema = object({
|
|
116456
116544
|
success: literal(true),
|
|
116457
116545
|
token: string$4(),
|
|
@@ -116555,7 +116643,7 @@ class GitHubTokenManager {
|
|
|
116555
116643
|
this.logger = options2.logger ?? getLogger("github-token");
|
|
116556
116644
|
this.client = new ConvexHttpClient(options2.serverUrl, {
|
|
116557
116645
|
logger: false,
|
|
116558
|
-
fetch: (
|
|
116646
|
+
fetch: withRequestDeadline(GITHUB_TOKEN_CLOUD_TIMEOUT_MS)
|
|
116559
116647
|
});
|
|
116560
116648
|
this.cliToken = options2.cliToken;
|
|
116561
116649
|
this.workspaceId = options2.workspaceId;
|
|
@@ -138086,82 +138174,6 @@ const clearGitHubTokenEnv = (env2) => {
|
|
|
138086
138174
|
if (GITHUB_CREDENTIAL_ENV_KEYS.includes(key2.toUpperCase())) delete env2[key2];
|
|
138087
138175
|
}
|
|
138088
138176
|
};
|
|
138089
|
-
const githubCredentialRuntime = String.raw`
|
|
138090
|
-
const credentialError = (code, details = {}) => Object.assign(new Error(code), { code, ...details });
|
|
138091
|
-
const errorCode = error => {
|
|
138092
|
-
if (error?.name === 'TimeoutError' || error?.name === 'AbortError') return 'timeout';
|
|
138093
|
-
const code = [error?.code, error?.cause?.code].find(value => typeof value === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(value));
|
|
138094
|
-
return typeof code === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(code) ? code : 'unexpected_error';
|
|
138095
|
-
};
|
|
138096
|
-
const diagnostic = (source, stage, error) => {
|
|
138097
|
-
const detail = { source, stage, code: errorCode(error) };
|
|
138098
|
-
if (Number.isInteger(error?.status)) detail.status = error.status;
|
|
138099
|
-
if (typeof error?.requestId === 'string' && /^[a-f0-9-]{1,64}$/.test(error.requestId)) detail.requestId = error.requestId;
|
|
138100
|
-
console.error('[Lody GitHub] ' + JSON.stringify(detail));
|
|
138101
|
-
return detail;
|
|
138102
|
-
};
|
|
138103
|
-
// This file is authored by the host, never inferred from a child's token/env.
|
|
138104
|
-
// A pinned context token names an immutable snapshot for host-side clone/fetch.
|
|
138105
|
-
const readCredentialContext = (fs, statePath, env) => {
|
|
138106
|
-
const file = env.LODY_GIT_CRED_CONTEXT_FILE || (env.LODY_GIT_CRED_CONTEXT_TOKEN && statePath + '.contexts/' + env.LODY_GIT_CRED_CONTEXT_TOKEN + '.json');
|
|
138107
|
-
if (!file) throw credentialError('context_missing');
|
|
138108
|
-
let context;
|
|
138109
|
-
try { context = JSON.parse(fs.readFileSync(file, 'utf8')); }
|
|
138110
|
-
catch (cause) { throw credentialError('context_unreadable', { cause }); }
|
|
138111
|
-
if (context?.version !== 1 || typeof context.contextToken !== 'string' || !context.contextToken || typeof context.allowLocalAuth !== 'boolean') throw credentialError('context_invalid');
|
|
138112
|
-
return context;
|
|
138113
|
-
};
|
|
138114
|
-
const readCredentialPolicy = () => {
|
|
138115
|
-
const context = getContext();
|
|
138116
|
-
return { allowLocalAuth: context.allowLocalAuth, personalEnabled: true };
|
|
138117
|
-
};
|
|
138118
|
-
const readManagedCandidate = async (repoFullName, source) => {
|
|
138119
|
-
const response = await requestBroker('/github-token', {
|
|
138120
|
-
repoFullName, source, contextToken: getContext().contextToken,
|
|
138121
|
-
}, 3000);
|
|
138122
|
-
if (!response) throw credentialError('broker_unavailable');
|
|
138123
|
-
let body;
|
|
138124
|
-
try { body = await response.json(); }
|
|
138125
|
-
catch (cause) { throw credentialError(errorCode(cause) === 'timeout' ? 'timeout' : 'invalid_response', { cause, status: response.status }); }
|
|
138126
|
-
if (!response.ok) throw credentialError(typeof body.error === 'string' && /^[A-Za-z0-9_]{1,64}$/.test(body.error) ? body.error : 'broker_http_error', { status: response.status, requestId: body.requestId });
|
|
138127
|
-
if (body.available === false) throw credentialError(typeof body.reason === 'string' && /^[a-z_]{1,64}$/.test(body.reason) ? body.reason : 'credential_unavailable');
|
|
138128
|
-
if (typeof body.token !== 'string' || !body.token || /[\r\n]/.test(body.token) || body.tokenSource !== source) throw credentialError('invalid_credential_response');
|
|
138129
|
-
return { token: body.token };
|
|
138130
|
-
};
|
|
138131
|
-
// One acquisition per source. Consumers can continue after a provably safe
|
|
138132
|
-
// failure of the actual operation; never restart this iterator to retry a source.
|
|
138133
|
-
async function* githubCredentials(repo, policy, localCandidate, anonymous = false) {
|
|
138134
|
-
const failures = [];
|
|
138135
|
-
for (const source of ['personal', 'local', 'app', ...(anonymous ? ['anonymous'] : [])]) {
|
|
138136
|
-
if (source === 'personal' && policy.personalEnabled === false) continue;
|
|
138137
|
-
if (source === 'local' && !policy.allowLocalAuth) continue;
|
|
138138
|
-
try {
|
|
138139
|
-
const candidate = source === 'anonymous' ? { token: null } : source === 'local' ? await localCandidate() : await readManagedCandidate(repo, source);
|
|
138140
|
-
if (!candidate) throw credentialError('credential_missing');
|
|
138141
|
-
yield { ...candidate, source };
|
|
138142
|
-
} catch (error) {
|
|
138143
|
-
failures.push(diagnostic(source, 'acquire', error));
|
|
138144
|
-
}
|
|
138145
|
-
}
|
|
138146
|
-
throw credentialError('credentials_exhausted', { failures });
|
|
138147
|
-
}
|
|
138148
|
-
const selectGitHubCredential = async (repo, policy, localCandidate, requireWrite, anonymousCandidate, verify = async () => true) => {
|
|
138149
|
-
const failures = [];
|
|
138150
|
-
try {
|
|
138151
|
-
for await (const candidate of githubCredentials(repo, policy, localCandidate, !requireWrite && !!anonymousCandidate)) {
|
|
138152
|
-
try {
|
|
138153
|
-
if (candidate.source === 'anonymous' && !await anonymousCandidate()) throw credentialError('anonymous_unavailable');
|
|
138154
|
-
if (!await verify(candidate)) throw credentialError('access_denied');
|
|
138155
|
-
console.error('[Lody GitHub] ' + JSON.stringify({ source: candidate.source, stage: 'selected', repo }));
|
|
138156
|
-
return candidate;
|
|
138157
|
-
} catch (error) { failures.push(diagnostic(candidate.source, 'access', error)); }
|
|
138158
|
-
}
|
|
138159
|
-
} catch (error) {
|
|
138160
|
-
if (error.code === 'credentials_exhausted') error.failures.push(...failures);
|
|
138161
|
-
throw error;
|
|
138162
|
-
}
|
|
138163
|
-
};
|
|
138164
|
-
`;
|
|
138165
138177
|
const ghPrCreateScript = String.raw`
|
|
138166
138178
|
const createPrViaRest = async (ghCommand, target, parsed, env) => {
|
|
138167
138179
|
const values = parsed.values;
|
|
@@ -138387,7 +138399,7 @@ const main = async () => {
|
|
|
138387
138399
|
if (token) return { token };
|
|
138388
138400
|
throw credentialError('unsupported_local_header');
|
|
138389
138401
|
}
|
|
138390
|
-
const fill = spawnSync(REAL_GIT, ['credential', 'fill'], { env: { ...env, LODY_GIT_LOCAL_DELEGATE: '1' }, input: 'protocol=https\nhost=github.com\npath=' + repo + '.git\n\n', encoding: 'utf8', timeout:
|
|
138402
|
+
const fill = spawnSync(REAL_GIT, ['credential', 'fill'], { env: { ...env, LODY_GIT_LOCAL_DELEGATE: '1' }, input: 'protocol=https\nhost=github.com\npath=' + repo + '.git\n\n', encoding: 'utf8', timeout: 10_000 });
|
|
138391
138403
|
if (fill.error) throw fill.error;
|
|
138392
138404
|
const token = /^password=(.*)$/m.exec(fill.stdout || '')?.[1];
|
|
138393
138405
|
if (token) return { token };
|
|
@@ -138398,14 +138410,14 @@ const main = async () => {
|
|
|
138398
138410
|
const env = candidate.ssh ? nativeEnv() : authenticatedEnv(httpsUrl, candidate.token);
|
|
138399
138411
|
if (candidate.ssh) {
|
|
138400
138412
|
const configured = spawnSync(REAL_GIT, ['config', '--get', 'core.sshCommand'], { env, encoding: 'utf8' });
|
|
138401
|
-
env.GIT_SSH_COMMAND = (env.GIT_SSH_COMMAND || configured.stdout?.trim() || (env.GIT_SSH ? quote(env.GIT_SSH) : 'ssh')) + sshPort + ' -oBatchMode=yes -oConnectTimeout=
|
|
138413
|
+
env.GIT_SSH_COMMAND = (env.GIT_SSH_COMMAND || configured.stdout?.trim() || (env.GIT_SSH ? quote(env.GIT_SSH) : 'ssh')) + sshPort + ' -oBatchMode=yes -oConnectTimeout=10';
|
|
138402
138414
|
}
|
|
138403
138415
|
// Native upload/receive-pack advertisement has no write effects. It lets
|
|
138404
138416
|
// denied credentials fall through without replaying an uncertain push.
|
|
138405
138417
|
const target = candidate.ssh ? (sshPort ? 'ssh://git@ssh.github.com:443/' : 'git@github.com:') + repo + '.git' : httpsUrl;
|
|
138406
138418
|
const args = candidate.ssh ? ['ls-remote', ...(write ? ['--upload-pack=git-receive-pack'] : []), target] : ['remote-https', 'lody-advertisement', target];
|
|
138407
138419
|
const result = spawnSync(REAL_GIT, args, {
|
|
138408
|
-
env, input: candidate.ssh ? undefined : (write ? 'list for-push\n\n' : 'list\n\n'), encoding: 'utf8', timeout:
|
|
138420
|
+
env, input: candidate.ssh ? undefined : (write ? 'list for-push\n\n' : 'list\n\n'), encoding: 'utf8', timeout: 15_000, maxBuffer: 1024 * 1024, stdio: ['pipe', 'ignore', 'pipe'],
|
|
138409
138421
|
});
|
|
138410
138422
|
if (result.error) throw result.error;
|
|
138411
138423
|
if (result.status !== 0) {
|
|
@@ -139144,7 +139156,7 @@ async function* ghEnvironments(ghCommand, args) {
|
|
|
139144
139156
|
const token = env.GH_TOKEN || env.GITHUB_TOKEN;
|
|
139145
139157
|
if (token) return { token };
|
|
139146
139158
|
const result = await runGhCommand(ghCommand, ['auth', 'token', '--hostname', target.host], {
|
|
139147
|
-
env, stdio: ['ignore', 'pipe', 'pipe'], timeout:
|
|
139159
|
+
env, stdio: ['ignore', 'pipe', 'pipe'], timeout: 10_000,
|
|
139148
139160
|
});
|
|
139149
139161
|
if (result.error) throw result.error;
|
|
139150
139162
|
if (result.status !== 0) throw credentialError('local_auth_missing');
|
|
@@ -145537,6 +145549,16 @@ const CatalogAccessSnapshotSchema = object({
|
|
|
145537
145549
|
ownerUserId: string$4(),
|
|
145538
145550
|
verifiedAt: string$4()
|
|
145539
145551
|
});
|
|
145552
|
+
const MEMBER_ACCESS_SNAPSHOT_TTL_MS = 60 * 60 * 1e3;
|
|
145553
|
+
const CatalogMemberAccessSnapshotSchema = object({
|
|
145554
|
+
requesterUserId: string$4(),
|
|
145555
|
+
localProjectId: string$4().optional(),
|
|
145556
|
+
// Optional only so an unbound entry parses (and never matches) instead of
|
|
145557
|
+
// making the whole catalog corrupt.
|
|
145558
|
+
ownerUserId: string$4().optional(),
|
|
145559
|
+
machineId: string$4().optional(),
|
|
145560
|
+
verifiedAt: string$4()
|
|
145561
|
+
});
|
|
145540
145562
|
const CatalogWorkspaceSchema = object({
|
|
145541
145563
|
workspaceId: string$4(),
|
|
145542
145564
|
name: string$4(),
|
|
@@ -145548,7 +145570,8 @@ const CatalogWorkspaceSchema = object({
|
|
|
145548
145570
|
machine: CatalogMachineSchema.extend({
|
|
145549
145571
|
cachedAt: number$3()
|
|
145550
145572
|
}).optional(),
|
|
145551
|
-
accessSnapshot: CatalogAccessSnapshotSchema.optional()
|
|
145573
|
+
accessSnapshot: CatalogAccessSnapshotSchema.optional(),
|
|
145574
|
+
memberAccessSnapshots: array$1(CatalogMemberAccessSnapshotSchema).optional()
|
|
145552
145575
|
});
|
|
145553
145576
|
const CatalogSessionSchema = object({
|
|
145554
145577
|
sessionId: string$4(),
|
|
@@ -145571,6 +145594,10 @@ class CatalogCorruptError extends TaggedError("CatalogCorruptError") {
|
|
|
145571
145594
|
}
|
|
145572
145595
|
class CatalogPermissionError extends TaggedError("CatalogPermissionError") {
|
|
145573
145596
|
}
|
|
145597
|
+
function isMemberAccessSnapshotFresh(snapshot2, nowMs2) {
|
|
145598
|
+
const ageMs = nowMs2 - Date.parse(snapshot2.verifiedAt);
|
|
145599
|
+
return ageMs >= 0 && ageMs < MEMBER_ACCESS_SNAPSHOT_TTL_MS;
|
|
145600
|
+
}
|
|
145574
145601
|
const emptyCatalog = () => ({
|
|
145575
145602
|
version: CATALOG_VERSION,
|
|
145576
145603
|
identity: null,
|
|
@@ -145721,6 +145748,7 @@ function makeLocalWorkspaceCatalog(options2 = {}) {
|
|
|
145721
145748
|
cacheRemoteWorkspaces: (input2) => mutate((snapshot2) => {
|
|
145722
145749
|
const now2 = getServerNow();
|
|
145723
145750
|
const remoteIds = new Set(input2.workspaces.map((workspace) => workspace.id));
|
|
145751
|
+
const keepMemberGrants = snapshot2.identity?.userId === input2.identity.userId && snapshot2.machine?.machineId === input2.machine.machineId;
|
|
145724
145752
|
const previousById = new Map(
|
|
145725
145753
|
snapshot2.workspaces.map((workspace) => [workspace.workspaceId, workspace])
|
|
145726
145754
|
);
|
|
@@ -145737,7 +145765,8 @@ function makeLocalWorkspaceCatalog(options2 = {}) {
|
|
|
145737
145765
|
...input2.machine,
|
|
145738
145766
|
cachedAt: now2
|
|
145739
145767
|
},
|
|
145740
|
-
...previous2?.accessSnapshot ? { accessSnapshot: previous2.accessSnapshot } : {}
|
|
145768
|
+
...previous2?.accessSnapshot ? { accessSnapshot: previous2.accessSnapshot } : {},
|
|
145769
|
+
...keepMemberGrants && previous2?.memberAccessSnapshots ? { memberAccessSnapshots: previous2.memberAccessSnapshots } : {}
|
|
145741
145770
|
};
|
|
145742
145771
|
});
|
|
145743
145772
|
const remoteMissing = snapshot2.workspaces.filter((workspace) => !remoteIds.has(workspace.workspaceId)).map((workspace) => ({
|
|
@@ -145765,6 +145794,32 @@ function makeLocalWorkspaceCatalog(options2 = {}) {
|
|
|
145765
145794
|
return { ...workspace, accessSnapshot: input2.accessSnapshot };
|
|
145766
145795
|
})
|
|
145767
145796
|
})),
|
|
145797
|
+
recordMemberAccessSnapshot: (input2) => mutate((snapshot2) => {
|
|
145798
|
+
const nowMs2 = clock2();
|
|
145799
|
+
return {
|
|
145800
|
+
...snapshot2,
|
|
145801
|
+
workspaces: snapshot2.workspaces.map((workspace) => {
|
|
145802
|
+
if (workspace.workspaceId !== input2.workspaceId) {
|
|
145803
|
+
return workspace;
|
|
145804
|
+
}
|
|
145805
|
+
const others = (workspace.memberAccessSnapshots ?? []).filter(
|
|
145806
|
+
(entry) => (entry.requesterUserId !== input2.requesterUserId || entry.localProjectId !== input2.localProjectId) && isMemberAccessSnapshotFresh(entry, nowMs2)
|
|
145807
|
+
);
|
|
145808
|
+
const next = input2.verifiedAt === null ? others : [
|
|
145809
|
+
...others,
|
|
145810
|
+
{
|
|
145811
|
+
requesterUserId: input2.requesterUserId,
|
|
145812
|
+
...input2.localProjectId ? { localProjectId: input2.localProjectId } : {},
|
|
145813
|
+
ownerUserId: input2.ownerUserId,
|
|
145814
|
+
machineId: input2.machineId,
|
|
145815
|
+
verifiedAt: input2.verifiedAt
|
|
145816
|
+
}
|
|
145817
|
+
].slice(-64);
|
|
145818
|
+
const { memberAccessSnapshots: _previous, ...rest } = workspace;
|
|
145819
|
+
return next.length > 0 ? { ...rest, memberAccessSnapshots: next } : rest;
|
|
145820
|
+
})
|
|
145821
|
+
};
|
|
145822
|
+
}),
|
|
145768
145823
|
upsertSession: (session2) => mutate((snapshot2) => {
|
|
145769
145824
|
const now2 = getServerNow();
|
|
145770
145825
|
const nextSession = { ...session2, cachedAt: now2 };
|
|
@@ -221442,13 +221497,15 @@ const defaultSandboxDeps = () => ({
|
|
|
221442
221497
|
configureExecutionProcess: async (pid, logger2) => {
|
|
221443
221498
|
await applyExecutionProcessResourceProfile(pid, logger2);
|
|
221444
221499
|
},
|
|
221445
|
-
killPid: (pid, signal) => nodeProcessLive.kill(pid, signal ?? "SIGTERM")
|
|
221500
|
+
killPid: (pid, signal) => nodeProcessLive.kill(pid, signal ?? "SIGTERM"),
|
|
221501
|
+
listProcessGroup: nodeProcessLive.listProcessGroup
|
|
221446
221502
|
});
|
|
221447
221503
|
const toNodeProcess = (deps) => ({
|
|
221448
221504
|
platform: deps.platform,
|
|
221449
221505
|
spawn: deps.spawnProcess,
|
|
221450
221506
|
spawnSync: nodeProcessLive.spawnSync,
|
|
221451
|
-
kill: (pid, signal) => deps.killPid(pid, signal)
|
|
221507
|
+
kill: (pid, signal) => deps.killPid(pid, signal),
|
|
221508
|
+
...deps.listProcessGroup ? { listProcessGroup: deps.listProcessGroup } : {}
|
|
221452
221509
|
});
|
|
221453
221510
|
const configureProcessBestEffort = (deps, logger2, prefix = "") => (pid) => tryPromise({
|
|
221454
221511
|
try: () => deps.configureExecutionProcess(pid, logger2),
|
|
@@ -221463,6 +221520,8 @@ const configureProcessBestEffort = (deps, logger2, prefix = "") => (pid) => tryP
|
|
|
221463
221520
|
function createSessionSandboxFactory(options2) {
|
|
221464
221521
|
const deps = {
|
|
221465
221522
|
...defaultSandboxDeps(),
|
|
221523
|
+
// A substituted process table must not be judged by the host's.
|
|
221524
|
+
...options2.deps?.killPid ? { listProcessGroup: void 0 } : {},
|
|
221466
221525
|
...options2.deps ?? {}
|
|
221467
221526
|
};
|
|
221468
221527
|
const facade = { logger: options2.logger, nodeProcess: toNodeProcess(deps) };
|
|
@@ -222127,15 +222186,11 @@ class Session2 extends EventEmitter {
|
|
|
222127
222186
|
const failures = [];
|
|
222128
222187
|
for (const outcome of await Promise.allSettled([
|
|
222129
222188
|
activeProcess?.terminate(termination.force),
|
|
222130
|
-
agentProcess?.terminate(termination.force)
|
|
222189
|
+
agentProcess?.terminate(termination.force),
|
|
222190
|
+
this.sandbox.terminate(termination.force)
|
|
222131
222191
|
])) {
|
|
222132
222192
|
if (outcome.status === "rejected") failures.push(outcome.reason);
|
|
222133
222193
|
}
|
|
222134
|
-
try {
|
|
222135
|
-
await this.sandbox.terminate(termination.force);
|
|
222136
|
-
} catch (error2) {
|
|
222137
|
-
failures.push(error2);
|
|
222138
|
-
}
|
|
222139
222194
|
await terminalsDisposed;
|
|
222140
222195
|
for (const failure2 of failures) {
|
|
222141
222196
|
this.logger.error(
|
|
@@ -225875,7 +225930,7 @@ async function applyTitleConfigOptions(options2) {
|
|
|
225875
225930
|
);
|
|
225876
225931
|
}
|
|
225877
225932
|
}
|
|
225878
|
-
const extractTitleChunkFromNotification = (notification
|
|
225933
|
+
const extractTitleChunkFromNotification = (notification) => {
|
|
225879
225934
|
const update2 = notification.update;
|
|
225880
225935
|
if (update2.sessionUpdate !== "agent_message_chunk") {
|
|
225881
225936
|
return null;
|
|
@@ -225885,12 +225940,6 @@ const extractTitleChunkFromNotification = (notification, agentType) => {
|
|
|
225885
225940
|
return null;
|
|
225886
225941
|
}
|
|
225887
225942
|
const phase = parseLodyMessagePhase(update2._meta);
|
|
225888
|
-
if (agentType === "codex") {
|
|
225889
|
-
if (phase !== "final_answer") {
|
|
225890
|
-
return null;
|
|
225891
|
-
}
|
|
225892
|
-
return content2.text;
|
|
225893
|
-
}
|
|
225894
225943
|
if (phase !== void 0 && phase !== "final_answer") {
|
|
225895
225944
|
return null;
|
|
225896
225945
|
}
|
|
@@ -225990,6 +226039,7 @@ const generateTitleIsolated = async (options2) => {
|
|
|
225990
226039
|
const sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
225991
226040
|
const tryGenerateWithArgs = async (extraArgs) => {
|
|
225992
226041
|
let collectedText = "";
|
|
226042
|
+
let unphasedText = "";
|
|
225993
226043
|
const startupStartedAt = Date.now();
|
|
225994
226044
|
options2.logger.debug(
|
|
225995
226045
|
`[title-generator] Starting isolated title ACP agent (cliType=${options2.cliType} agentType=${options2.agentType})`
|
|
@@ -226008,9 +226058,13 @@ const generateTitleIsolated = async (options2) => {
|
|
|
226008
226058
|
terminalManager: noopTerminalManager,
|
|
226009
226059
|
terminalEnabled: false,
|
|
226010
226060
|
onUpdateMessage: (msg) => {
|
|
226011
|
-
const text2 = extractTitleChunkFromNotification(msg
|
|
226061
|
+
const text2 = extractTitleChunkFromNotification(msg);
|
|
226012
226062
|
if (text2) {
|
|
226013
|
-
|
|
226063
|
+
if (parseLodyMessagePhase(msg.update._meta) === "final_answer") {
|
|
226064
|
+
collectedText += text2;
|
|
226065
|
+
} else {
|
|
226066
|
+
unphasedText += text2;
|
|
226067
|
+
}
|
|
226014
226068
|
}
|
|
226015
226069
|
},
|
|
226016
226070
|
onRequestPermission: async (_requestId, _request) => ({ outcome: { outcome: "cancelled" } }),
|
|
@@ -226040,16 +226094,19 @@ const generateTitleIsolated = async (options2) => {
|
|
|
226040
226094
|
}
|
|
226041
226095
|
}
|
|
226042
226096
|
collectedText = "";
|
|
226097
|
+
unphasedText = "";
|
|
226043
226098
|
options2.logger.debug(`[title-generator] Sending title prompt (acpSessionId=${acpSessionId})`);
|
|
226044
226099
|
const response2 = await client2?.prompt(acpSessionId, prompt2);
|
|
226045
226100
|
options2.logger.debug(
|
|
226046
226101
|
`[title-generator] Title prompt returned (acpSessionId=${acpSessionId})`
|
|
226047
226102
|
);
|
|
226048
226103
|
const deadline = Date.now() + 1e4;
|
|
226049
|
-
while (Date.now() < deadline && collectedText.trim() === "") {
|
|
226104
|
+
while (Date.now() < deadline && collectedText.trim() === "" && unphasedText.trim() === "") {
|
|
226050
226105
|
await sleep2(100);
|
|
226051
226106
|
}
|
|
226052
|
-
const fromStream = sanitizeGeneratedTitle(
|
|
226107
|
+
const fromStream = sanitizeGeneratedTitle(
|
|
226108
|
+
collectedText.trim() ? collectedText : unphasedText
|
|
226109
|
+
);
|
|
226053
226110
|
if (fromStream) {
|
|
226054
226111
|
return fromStream;
|
|
226055
226112
|
}
|
|
@@ -229950,6 +230007,7 @@ class SessionExecutionService {
|
|
|
229950
230007
|
}
|
|
229951
230008
|
if (access2.outcome === "indeterminate") {
|
|
229952
230009
|
outcome = "access-indeterminate";
|
|
230010
|
+
ctx.runtime.withdrawInboxExecution = true;
|
|
229953
230011
|
yield* self2.tryPromise(async () => await options2.onAccessIndeterminate(access2));
|
|
229954
230012
|
return void 0;
|
|
229955
230013
|
}
|
|
@@ -230417,6 +230475,23 @@ class SessionExecutionService {
|
|
|
230417
230475
|
await options2.sessionDoc.setStatus(SessionStatusFactory.idle());
|
|
230418
230476
|
this.captureStatusChanged(options2.sessionId, "idle", void 0, "turn_failed");
|
|
230419
230477
|
}
|
|
230478
|
+
/**
|
|
230479
|
+
* Fail a still-pending user turn whose Inbox input already ended in an earlier
|
|
230480
|
+
* execution. Lody never replays such an input, so the user resends instead.
|
|
230481
|
+
*/
|
|
230482
|
+
async retireEndedInboxInputTurn(sessionId, sessionDoc, userTurnId) {
|
|
230483
|
+
const read2 = await (await createSessionBackend(sessionDoc)).readTurn(userTurnId);
|
|
230484
|
+
if (read2.state === "ready" && (read2.turn.role !== "user" || ["handled", "failed", "canceled", "delivery_unknown"].includes(read2.turn.status ?? ""))) {
|
|
230485
|
+
return;
|
|
230486
|
+
}
|
|
230487
|
+
await this.recordKnownChatFailure({
|
|
230488
|
+
sessionId,
|
|
230489
|
+
sessionDoc,
|
|
230490
|
+
userTurnId,
|
|
230491
|
+
reason: "turn_pre_prompt_failed",
|
|
230492
|
+
message: "This message was not started because an earlier attempt to run it already ended. Lody does not replay messages automatically; send it again to retry."
|
|
230493
|
+
});
|
|
230494
|
+
}
|
|
230420
230495
|
formatMemoryPressureFailureMessage(result2) {
|
|
230421
230496
|
if (result2.pressureReason === "darwin_pressure_critical") {
|
|
230422
230497
|
return "The machine is at critical memory pressure — macOS is reclaiming memory and terminating processes to keep up. The turn was not started; free memory and retry.";
|
|
@@ -230974,6 +231049,15 @@ class SessionExecutionService {
|
|
|
230974
231049
|
"Inbox preparation and release failed"
|
|
230975
231050
|
);
|
|
230976
231051
|
}
|
|
231052
|
+
if (!runtime.releaseFailure && userTurnId && inboxInput && !options2.inboxBatch && inbox.inputEnded(this.deps.workspaceId, sessionId, inboxInput.inputId)) {
|
|
231053
|
+
await this.retireEndedInboxInputTurn(sessionId, sessionDoc, userTurnId).catch(
|
|
231054
|
+
(retireCause) => this.deps.logger.warn(
|
|
231055
|
+
`[${sessionId}] Failed to retire ended Inbox input ${userTurnId}: ${formatErrorMessage(retireCause)}`
|
|
231056
|
+
)
|
|
231057
|
+
);
|
|
231058
|
+
span.end({ outcome: "inbox-input-ended" });
|
|
231059
|
+
return "inbox-input-ended";
|
|
231060
|
+
}
|
|
230977
231061
|
span.end({ outcome: "inbox-prepare-failed" });
|
|
230978
231062
|
throw cause;
|
|
230979
231063
|
}
|
|
@@ -231394,7 +231478,13 @@ class SessionExecutionService {
|
|
|
231394
231478
|
}
|
|
231395
231479
|
span.end({ outcome, turnId });
|
|
231396
231480
|
}
|
|
231397
|
-
|
|
231481
|
+
const withdrawn = inboxInput && runtime.withdrawInboxExecution && !runtime.promptStarted && !runtime.cancelRequested && !runtime.releaseFailure && await runtime.inboxOwner.withdraw().catch((cause) => {
|
|
231482
|
+
this.deps.logger.warn(
|
|
231483
|
+
`[${sessionId}] Inbox withdraw failed; releasing instead: ${formatErrorMessage(cause)}`
|
|
231484
|
+
);
|
|
231485
|
+
return false;
|
|
231486
|
+
});
|
|
231487
|
+
if (inboxInput && !withdrawn) {
|
|
231398
231488
|
if (inboxBatch)
|
|
231399
231489
|
await (await createSessionBackend(sessionDoc)).applyHistoryAction({
|
|
231400
231490
|
kind: "operation-batch-status",
|
|
@@ -235416,11 +235506,14 @@ class SessionDispatchWatcher {
|
|
|
235416
235506
|
});
|
|
235417
235507
|
let executionAccessPromise = accessPromise;
|
|
235418
235508
|
let ownerRecheckStarted = false;
|
|
235509
|
+
this.recordMemberAccessVerdict(sessionId, requesterUserId, localProjectId, accessPromise);
|
|
235419
235510
|
const localAccess = this.deps.accessPolicy && this.deps.currentUserId ? await runPromise(
|
|
235420
235511
|
this.deps.accessPolicy.decide({
|
|
235421
235512
|
workspaceId: this.deps.workspaceId,
|
|
235422
235513
|
currentUserId: this.deps.currentUserId,
|
|
235423
|
-
requesterUserId
|
|
235514
|
+
requesterUserId,
|
|
235515
|
+
machineId: this.deps.machineId,
|
|
235516
|
+
...localProjectId ? { localProjectId } : {}
|
|
235424
235517
|
})
|
|
235425
235518
|
) : { outcome: "remote" };
|
|
235426
235519
|
if (!isActive()) {
|
|
@@ -235544,6 +235637,31 @@ class SessionDispatchWatcher {
|
|
|
235544
235637
|
);
|
|
235545
235638
|
});
|
|
235546
235639
|
}
|
|
235640
|
+
/**
|
|
235641
|
+
* Maintain the member optimistic-allow cache from a backend verdict for a
|
|
235642
|
+
* requester who is not the machine owner. Only definitive verdicts write;
|
|
235643
|
+
* fire-and-forget like the owner recheck, so it never affects dispatch.
|
|
235644
|
+
*/
|
|
235645
|
+
recordMemberAccessVerdict(sessionId, requesterUserId, localProjectId, verdict) {
|
|
235646
|
+
const record2 = this.deps.recordMemberAccessSnapshot;
|
|
235647
|
+
if (!record2 || !this.deps.currentUserId || requesterUserId === this.deps.currentUserId) {
|
|
235648
|
+
void verdict.catch(() => void 0);
|
|
235649
|
+
return;
|
|
235650
|
+
}
|
|
235651
|
+
void (async () => {
|
|
235652
|
+
const access2 = await verdict;
|
|
235653
|
+
if (access2.outcome === "indeterminate") return;
|
|
235654
|
+
await record2({
|
|
235655
|
+
requesterUserId,
|
|
235656
|
+
...localProjectId ? { localProjectId } : {},
|
|
235657
|
+
verdict: access2.outcome
|
|
235658
|
+
});
|
|
235659
|
+
})().catch((error2) => {
|
|
235660
|
+
this.deps.logger.debug(
|
|
235661
|
+
`[${sessionId}] Failed to record member access verdict: ${formatErrorMessage(error2)}`
|
|
235662
|
+
);
|
|
235663
|
+
});
|
|
235664
|
+
}
|
|
235547
235665
|
/**
|
|
235548
235666
|
* Fork a background verify-with-retry for a transient access failure on `turnId`.
|
|
235549
235667
|
*
|
|
@@ -235582,6 +235700,12 @@ class SessionDispatchWatcher {
|
|
|
235582
235700
|
}).pipe(
|
|
235583
235701
|
flatMap$1(
|
|
235584
235702
|
() => sync(() => {
|
|
235703
|
+
this.recordMemberAccessVerdict(
|
|
235704
|
+
sessionId,
|
|
235705
|
+
verifyArgs.requesterUserId,
|
|
235706
|
+
verifyArgs.localProjectId,
|
|
235707
|
+
Promise.resolve({ outcome: "allowed" })
|
|
235708
|
+
);
|
|
235585
235709
|
this.clearAccessFiberIf(sessionId, turnId);
|
|
235586
235710
|
void this.enqueueSessionCheck(sessionId);
|
|
235587
235711
|
})
|
|
@@ -235590,6 +235714,12 @@ class SessionDispatchWatcher {
|
|
|
235590
235714
|
"AccessDenied",
|
|
235591
235715
|
(denied) => promise(async () => {
|
|
235592
235716
|
this.clearAccessFiberIf(sessionId, turnId);
|
|
235717
|
+
this.recordMemberAccessVerdict(
|
|
235718
|
+
sessionId,
|
|
235719
|
+
verifyArgs.requesterUserId,
|
|
235720
|
+
verifyArgs.localProjectId,
|
|
235721
|
+
Promise.resolve({ outcome: "denied", reason: denied.reason })
|
|
235722
|
+
);
|
|
235593
235723
|
await this.markDispatchAccessDenied(sessionId, sessionDoc, turnId, denied.reason).catch(
|
|
235594
235724
|
(error2) => {
|
|
235595
235725
|
this.deps.logger.error(
|
|
@@ -238916,6 +239046,9 @@ class OperationInbox extends Service()("lody/orchestration/OperationInbox") {
|
|
|
238916
239046
|
begin: fn("OperationInbox.begin")(function* (s2, id2) {
|
|
238917
239047
|
return yield* withGate(s2, repo.begin(s2, id2, owner2));
|
|
238918
239048
|
}),
|
|
239049
|
+
withdraw: fn("OperationInbox.withdraw")(function* (i, id2) {
|
|
239050
|
+
return yield* withGate(i, repo.withdraw(i, id2));
|
|
239051
|
+
}),
|
|
238919
239052
|
pause: fn("OperationInbox.pause")(function* (s2, id2, ids, cancelId) {
|
|
238920
239053
|
return yield* withGate(
|
|
238921
239054
|
s2,
|
|
@@ -239113,6 +239246,19 @@ const makeExecutionOwner = fnUntraced(function* (initial, id2, initialBatch) {
|
|
|
239113
239246
|
return start2();
|
|
239114
239247
|
}).pipe(tap$1(() => batch ? inbox.settle(batch, "submitted") : void_$1)),
|
|
239115
239248
|
finish: (outcome, cause) => releaseGate.withPermit(finishWork(outcome, cause)),
|
|
239249
|
+
/** Return an unsubmitted, resource-free execution's input to pending; false if ineligible. */
|
|
239250
|
+
withdraw: releaseGate.withPermit(
|
|
239251
|
+
gen(function* () {
|
|
239252
|
+
if (firstFinish || phase !== "prepared" || resources.size > 0 || rawRequests.length > 0)
|
|
239253
|
+
return false;
|
|
239254
|
+
if (!(yield* inbox.withdraw(input2, id2))) return false;
|
|
239255
|
+
firstFinish = void_;
|
|
239256
|
+
phase = "released";
|
|
239257
|
+
yield* detach;
|
|
239258
|
+
yield* succeed$5(released, void 0);
|
|
239259
|
+
return true;
|
|
239260
|
+
}).pipe(uninterruptible)
|
|
239261
|
+
),
|
|
239116
239262
|
awaitReleased: _await(released),
|
|
239117
239263
|
detach,
|
|
239118
239264
|
recover: (prepare, beforeRelease) => releaseGate.withPermit(recoverWork(prepare, beforeRelease).pipe(uninterruptible))
|
|
@@ -239136,6 +239282,7 @@ const makeInboxQueries = (sql) => {
|
|
|
239136
239282
|
return {
|
|
239137
239283
|
preferredHumanInput: (w2, s2) => io(() => sql.preferredHumanInput(w2, s2)),
|
|
239138
239284
|
inputCancellationReason: (w2, s2, id2) => io(() => sql.inputCancellationReason(w2, s2, id2)),
|
|
239285
|
+
inputEnded: (w2, s2, id2) => io(() => sql.inputEnded(w2, s2, id2)),
|
|
239139
239286
|
inputCanceled: (w2, s2, id2) => io(() => sql.inputCanceled(w2, s2, id2)),
|
|
239140
239287
|
inputKind: (s2, id2) => io(() => sql.inputKind(s2, id2)),
|
|
239141
239288
|
pauseTarget: (w2, s2, id2) => io(() => sql.pauseTarget(w2, s2, id2))
|
|
@@ -239161,6 +239308,7 @@ const inboxRepositoryLayer = (sql, ownedConnection = false) => {
|
|
|
239161
239308
|
canSubmit: (s2, id2, o) => io(() => sql.canSubmit(s2, id2, o)),
|
|
239162
239309
|
accept: (i) => io(() => sql.accept(i)),
|
|
239163
239310
|
begin: (s2, id2, owner2) => io(() => sql.begin(s2, id2, owner2)),
|
|
239311
|
+
withdraw: (i, id2) => io(() => sql.withdraw(i, id2)),
|
|
239164
239312
|
pause: (s2, id2, ids, cancelId) => io(() => sql.pause(s2, id2, ids, cancelId)),
|
|
239165
239313
|
release: (e) => io(() => sql.release(e)),
|
|
239166
239314
|
prepare: (i, o, id2) => io(() => sql.prepare(i, o, id2)),
|
|
@@ -239505,6 +239653,7 @@ const operationInboxLegacy = (options2) => {
|
|
|
239505
239653
|
return {
|
|
239506
239654
|
preferredHumanInput: (w2, s2) => runSync$1(queries.preferredHumanInput(w2, s2)),
|
|
239507
239655
|
inputCancellationReason: (w2, s2, id2) => runSync$1(queries.inputCancellationReason(w2, s2, id2)),
|
|
239656
|
+
inputEnded: (w2, s2, id2) => runSync$1(queries.inputEnded(w2, s2, id2)),
|
|
239508
239657
|
inputCanceled: (w2, s2, id2) => runSync$1(queries.inputCanceled(w2, s2, id2)),
|
|
239509
239658
|
inputKind: (s2, id2) => runSync$1(queries.inputKind(s2, id2)),
|
|
239510
239659
|
pauseTarget: (w2, s2, id2) => runSync$1(queries.pauseTarget(w2, s2, id2)),
|
|
@@ -239531,6 +239680,7 @@ const operationInboxLegacy = (options2) => {
|
|
|
239531
239680
|
steer: (start2) => runtime.runPromise(owner2.steer(start2)),
|
|
239532
239681
|
submit: (start2) => runtime.runPromise(owner2.submit(start2)),
|
|
239533
239682
|
finish: (outcome, cause) => runtime.runPromise(owner2.finish(outcome, cause)),
|
|
239683
|
+
withdraw: () => runtime.runPromise(owner2.withdraw),
|
|
239534
239684
|
detach: () => runtime.runSync(owner2.detach),
|
|
239535
239685
|
retain: (resource) => runtime.runSync(owner2.retain(resource)),
|
|
239536
239686
|
recover: (prepare, beforeRelease) => runtime.runPromise(
|
|
@@ -240038,6 +240188,13 @@ class InboxSqlite {
|
|
|
240038
240188
|
).get(workspaceId, sessionId, inputId);
|
|
240039
240189
|
return row2?.cancellation_reason === "user_stop" ? "user_stop" : void 0;
|
|
240040
240190
|
}
|
|
240191
|
+
/** True once an input finished or was canceled; `begin` never admits it again. */
|
|
240192
|
+
inputEnded(workspaceId, sessionId, inputId) {
|
|
240193
|
+
const row2 = this.db.prepare(
|
|
240194
|
+
"SELECT canceled,finished FROM inbox_inputs WHERE workspace_id=? AND session_id=? AND input_id=?"
|
|
240195
|
+
).get(workspaceId, sessionId, inputId);
|
|
240196
|
+
return row2?.canceled === 1 || row2?.finished === 1;
|
|
240197
|
+
}
|
|
240041
240198
|
inputCanceled(workspaceId, sessionId, inputId) {
|
|
240042
240199
|
const row2 = this.db.prepare(
|
|
240043
240200
|
"SELECT canceled FROM inbox_inputs WHERE workspace_id=? AND session_id=? AND input_id=?"
|
|
@@ -240158,6 +240315,38 @@ class InboxSqlite {
|
|
|
240158
240315
|
).run(executionId, "inputId" in s2 ? s2.inputId : null, s2.workspaceId, s2.sessionId, s2.userId).changes === 1;
|
|
240159
240316
|
});
|
|
240160
240317
|
}
|
|
240318
|
+
/**
|
|
240319
|
+
* Undo `begin` for an execution that submitted nothing and acquired nothing,
|
|
240320
|
+
* such as a turn whose machine access is still unverified. No release receipt is
|
|
240321
|
+
* written and the input stays unfinished, so the same execution id may begin it
|
|
240322
|
+
* again; prepared batch claims stay with the input.
|
|
240323
|
+
*/
|
|
240324
|
+
withdraw(s2, executionId) {
|
|
240325
|
+
return this.transaction(() => {
|
|
240326
|
+
const current2 = this.state(s2);
|
|
240327
|
+
if (current2.active_execution !== executionId || current2.active_input !== s2.inputId)
|
|
240328
|
+
return false;
|
|
240329
|
+
const used = this.db.prepare(
|
|
240330
|
+
`SELECT 1 FROM inbox_releases WHERE workspace_id=? AND session_id=? AND execution_id=?
|
|
240331
|
+
UNION ALL SELECT 1 FROM inbox_resources WHERE workspace_id=? AND session_id=? AND execution_id=?
|
|
240332
|
+
UNION ALL SELECT 1 FROM inbox_batches WHERE workspace_id=? AND session_id=? AND input_id=? AND state NOT IN ('prepared','superseded')`
|
|
240333
|
+
).get(
|
|
240334
|
+
s2.workspaceId,
|
|
240335
|
+
s2.sessionId,
|
|
240336
|
+
executionId,
|
|
240337
|
+
s2.workspaceId,
|
|
240338
|
+
s2.sessionId,
|
|
240339
|
+
executionId,
|
|
240340
|
+
s2.workspaceId,
|
|
240341
|
+
s2.sessionId,
|
|
240342
|
+
s2.inputId
|
|
240343
|
+
);
|
|
240344
|
+
if (used) return false;
|
|
240345
|
+
return this.db.prepare(
|
|
240346
|
+
"UPDATE inbox_sessions SET active_execution=NULL WHERE workspace_id=? AND session_id=? AND active_execution=?"
|
|
240347
|
+
).run(s2.workspaceId, s2.sessionId, executionId).changes === 1;
|
|
240348
|
+
});
|
|
240349
|
+
}
|
|
240161
240350
|
release(event) {
|
|
240162
240351
|
const prior = this.db.prepare(
|
|
240163
240352
|
"SELECT outcome,user_id FROM inbox_releases WHERE workspace_id=? AND session_id=? AND execution_id=?"
|
|
@@ -249825,7 +250014,7 @@ const session = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
249825
250014
|
withBuiltinDefaultTurnMode
|
|
249826
250015
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
249827
250016
|
const LOCAL_POLICY_DENY_REASON = "not_visible";
|
|
249828
|
-
function decideSessionAccessFromCatalog(snapshot2, input2) {
|
|
250017
|
+
function decideSessionAccessFromCatalog(snapshot2, input2, nowMs2) {
|
|
249829
250018
|
const workspace = snapshot2.workspaces.find((item) => item.workspaceId === input2.workspaceId);
|
|
249830
250019
|
if (!workspace) {
|
|
249831
250020
|
return { outcome: "remote" };
|
|
@@ -249836,6 +250025,12 @@ function decideSessionAccessFromCatalog(snapshot2, input2) {
|
|
|
249836
250025
|
if (workspace.state === "remote_missing") {
|
|
249837
250026
|
return { outcome: "deny", reason: LOCAL_POLICY_DENY_REASON, source: "remote_missing" };
|
|
249838
250027
|
}
|
|
250028
|
+
if (input2.requesterUserId !== input2.currentUserId) {
|
|
250029
|
+
const member2 = workspace.memberAccessSnapshots?.find(
|
|
250030
|
+
(entry) => entry.requesterUserId === input2.requesterUserId && entry.localProjectId === input2.localProjectId && entry.ownerUserId === input2.currentUserId && input2.machineId !== void 0 && entry.machineId === input2.machineId
|
|
250031
|
+
);
|
|
250032
|
+
return member2 && isMemberAccessSnapshotFresh(member2, nowMs2) ? { outcome: "allow", source: "member-cached" } : { outcome: "remote" };
|
|
250033
|
+
}
|
|
249839
250034
|
const accessSnapshot = workspace.accessSnapshot;
|
|
249840
250035
|
if (!accessSnapshot) {
|
|
249841
250036
|
return { outcome: "remote" };
|
|
@@ -249843,15 +250038,12 @@ function decideSessionAccessFromCatalog(snapshot2, input2) {
|
|
|
249843
250038
|
if (accessSnapshot.ownerUserId !== input2.currentUserId) {
|
|
249844
250039
|
return { outcome: "remote" };
|
|
249845
250040
|
}
|
|
249846
|
-
if (input2.requesterUserId !== input2.currentUserId) {
|
|
249847
|
-
return { outcome: "remote" };
|
|
249848
|
-
}
|
|
249849
250041
|
return { outcome: "allow", source: "owner-cached" };
|
|
249850
250042
|
}
|
|
249851
|
-
function makeSessionAccessPolicy(catalog) {
|
|
250043
|
+
function makeSessionAccessPolicy(catalog, now2 = getServerNow) {
|
|
249852
250044
|
return {
|
|
249853
250045
|
decide: (input2) => catalog.read().pipe(
|
|
249854
|
-
map$4((snapshot2) => decideSessionAccessFromCatalog(snapshot2, input2)),
|
|
250046
|
+
map$4((snapshot2) => decideSessionAccessFromCatalog(snapshot2, input2, now2())),
|
|
249855
250047
|
// Missing/corrupt catalogs already self-recover inside read(). Anything
|
|
249856
250048
|
// that still fails (e.g. EACCES on ~/.lody) must not strand the turn in
|
|
249857
250049
|
// a dispatch check that errors forever: degrade to the remote
|
|
@@ -256300,6 +256492,18 @@ class MessageHandler {
|
|
|
256300
256492
|
}
|
|
256301
256493
|
await this.recordWorkspaceAccessSnapshot(null);
|
|
256302
256494
|
},
|
|
256495
|
+
// Members get a TTL-bounded cached allow refreshed by every confirmed
|
|
256496
|
+
// backend allow and cleared by a definitive deny.
|
|
256497
|
+
recordMemberAccessSnapshot: async ({ requesterUserId, localProjectId, verdict }) => await fileLocksLegacy.runPromise(
|
|
256498
|
+
this.localWorkspaceCatalog.recordMemberAccessSnapshot({
|
|
256499
|
+
workspaceId: this.workspaceId,
|
|
256500
|
+
requesterUserId,
|
|
256501
|
+
...localProjectId ? { localProjectId } : {},
|
|
256502
|
+
ownerUserId: this.userId,
|
|
256503
|
+
machineId: this.machineId,
|
|
256504
|
+
verifiedAt: verdict === "allowed" ? new Date(getServerNow()).toISOString() : null
|
|
256505
|
+
})
|
|
256506
|
+
),
|
|
256303
256507
|
recordChatFailure: async (sessionDoc, reason, message) => await this.recordChatFailure(sessionDoc, reason, message),
|
|
256304
256508
|
onStartupBootstrapComplete: () => {
|
|
256305
256509
|
void this.resetMachineDisconnectedSessionsToIdle().catch((error2) => {
|
|
@@ -260446,7 +260650,7 @@ class MessageHandler {
|
|
|
260446
260650
|
const { sessionId, name: name2, arguments: args2 } = request2.params;
|
|
260447
260651
|
if (request2.workspaceId !== this.workspaceId || request2.machineId !== this.machineId || request2.ownerSessionId !== sessionId)
|
|
260448
260652
|
throw new Error("Session tool scope mismatch");
|
|
260449
|
-
const { executeDaemonSessionTool } = await import("./chunks/daemon-session-tools-
|
|
260653
|
+
const { executeDaemonSessionTool } = await import("./chunks/daemon-session-tools-Bgq2Cj2S.js");
|
|
260450
260654
|
const sourceWorkdir = this.resolveSessionWorkspaceRoot(sessionId);
|
|
260451
260655
|
if (!sourceWorkdir && args2 && typeof args2 === "object" && "attachments" in args2)
|
|
260452
260656
|
throw new Error("Requester Session workspace is unavailable");
|
|
@@ -265106,6 +265310,7 @@ const LODY_GIT_CRED_CONTEXT_TOKEN_ENV = "LODY_GIT_CRED_CONTEXT_TOKEN";
|
|
|
265106
265310
|
const LODY_GIT_CRED_CONTEXT_FILE_ENV = "LODY_GIT_CRED_CONTEXT_FILE";
|
|
265107
265311
|
class GitCredentialContextError extends TaggedError("GitCredentialContextError") {
|
|
265108
265312
|
}
|
|
265313
|
+
const SLOW_TOKEN_LOG_THRESHOLD_MS = 2e3;
|
|
265109
265314
|
const createGitCredentialBrokerHandler = (options2) => {
|
|
265110
265315
|
const handleRequest2 = async (req, res) => {
|
|
265111
265316
|
const requestId = randomBytes$4(8).toString("hex");
|
|
@@ -265210,6 +265415,12 @@ const createGitCredentialBrokerHandler = (options2) => {
|
|
|
265210
265415
|
typeof obj?.invalidatedPersonalToken === "string" ? obj.invalidatedPersonalToken : void 0
|
|
265211
265416
|
);
|
|
265212
265417
|
if (!isContextCurrent()) return;
|
|
265418
|
+
const elapsedMs = Date.now() - startedAt;
|
|
265419
|
+
if (elapsedMs >= SLOW_TOKEN_LOG_THRESHOLD_MS) {
|
|
265420
|
+
options2.logger.debug(
|
|
265421
|
+
`[git-cred-broker] ${JSON.stringify({ requestId, path: req.url, source: source2, code: "slow_ok", elapsedMs })}`
|
|
265422
|
+
);
|
|
265423
|
+
}
|
|
265213
265424
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
265214
265425
|
res.end(
|
|
265215
265426
|
JSON.stringify(
|
|
@@ -265701,9 +265912,28 @@ function makePreparationControlLegacy(hardTtlMs, onExpired) {
|
|
|
265701
265912
|
};
|
|
265702
265913
|
}
|
|
265703
265914
|
class SessionPreparationCleanupError extends Error {
|
|
265704
|
-
|
|
265915
|
+
retry;
|
|
265916
|
+
constructor(cause, retry2) {
|
|
265705
265917
|
super(`Session preparation cleanup failed: ${formatErrorMessage(cause)}`, { cause });
|
|
265706
265918
|
this.name = "SessionPreparationCleanupError";
|
|
265919
|
+
this.retry = retry2;
|
|
265920
|
+
}
|
|
265921
|
+
}
|
|
265922
|
+
class Retirement {
|
|
265923
|
+
constructor(release2) {
|
|
265924
|
+
this.release = release2;
|
|
265925
|
+
}
|
|
265926
|
+
attempt = null;
|
|
265927
|
+
failed = false;
|
|
265928
|
+
run() {
|
|
265929
|
+
if (this.attempt && !this.failed) return this.attempt;
|
|
265930
|
+
this.failed = false;
|
|
265931
|
+
const attempt2 = Promise.resolve().then(this.release);
|
|
265932
|
+
this.attempt = attempt2;
|
|
265933
|
+
attempt2.catch(() => {
|
|
265934
|
+
if (this.attempt === attempt2) this.failed = true;
|
|
265935
|
+
});
|
|
265936
|
+
return attempt2;
|
|
265707
265937
|
}
|
|
265708
265938
|
}
|
|
265709
265939
|
class SessionPreparationService {
|
|
@@ -265720,7 +265950,7 @@ class SessionPreparationService {
|
|
|
265720
265950
|
}
|
|
265721
265951
|
if (current2 && current2.requesterUserId !== args2.requesterUserId) return "busy";
|
|
265722
265952
|
let disposition = "accepted";
|
|
265723
|
-
let predecessorCleanup = this.
|
|
265953
|
+
let predecessorCleanup = this.retirementOf(args2.sessionId);
|
|
265724
265954
|
const requesterRecord = Array.from(this.records.values()).find(
|
|
265725
265955
|
(record22) => record22.requesterUserId === args2.requesterUserId
|
|
265726
265956
|
);
|
|
@@ -265798,7 +266028,7 @@ class SessionPreparationService {
|
|
|
265798
266028
|
}
|
|
265799
266029
|
discard(sessionId) {
|
|
265800
266030
|
const record2 = this.records.get(sessionId);
|
|
265801
|
-
if (!record2) return this.
|
|
266031
|
+
if (!record2) return this.retirementOf(sessionId);
|
|
265802
266032
|
return this.expire(record2, "expired");
|
|
265803
266033
|
}
|
|
265804
266034
|
peek(args2) {
|
|
@@ -265811,7 +266041,7 @@ class SessionPreparationService {
|
|
|
265811
266041
|
claim(args2) {
|
|
265812
266042
|
const record2 = this.records.get(args2.sessionId);
|
|
265813
266043
|
if (!record2) {
|
|
265814
|
-
return { status: "miss", cleanup: this.
|
|
266044
|
+
return { status: "miss", cleanup: this.retirementOf(args2.sessionId) };
|
|
265815
266045
|
}
|
|
265816
266046
|
if (record2.requesterUserId !== args2.requesterUserId || record2.claimKey !== args2.claimKey || !record2.resource) {
|
|
265817
266047
|
return { status: "miss", cleanup: this.expire(record2, "expired") };
|
|
@@ -265839,7 +266069,7 @@ class SessionPreparationService {
|
|
|
265839
266069
|
for (const record2 of records) {
|
|
265840
266070
|
void this.expire(record2, "expired");
|
|
265841
266071
|
}
|
|
265842
|
-
await Promise.allSettled(Array.from(this.retiring.values()));
|
|
266072
|
+
await Promise.allSettled(Array.from(this.retiring.values(), (retirement) => retirement.run()));
|
|
265843
266073
|
}
|
|
265844
266074
|
advance(record2, state2) {
|
|
265845
266075
|
if (this.records.get(record2.sessionId) !== record2 || record2.state === "claimed") {
|
|
@@ -265859,28 +266089,32 @@ class SessionPreparationService {
|
|
|
265859
266089
|
);
|
|
265860
266090
|
void this.expire(record2, "failed");
|
|
265861
266091
|
}
|
|
266092
|
+
/** The session's pending retirement, retrying it first if its last attempt failed. */
|
|
266093
|
+
retirementOf(sessionId) {
|
|
266094
|
+
return this.retiring.get(sessionId)?.run() ?? null;
|
|
266095
|
+
}
|
|
265862
266096
|
expire(record2, state2) {
|
|
265863
|
-
if (record2.
|
|
266097
|
+
if (record2.retirement) return record2.retirement.run();
|
|
265864
266098
|
if (this.records.get(record2.sessionId) === record2) {
|
|
265865
266099
|
this.records.delete(record2.sessionId);
|
|
265866
266100
|
}
|
|
265867
266101
|
record2.state = state2;
|
|
265868
266102
|
const controlClosed = record2.control.close();
|
|
265869
266103
|
const predecessor = this.retiring.get(record2.sessionId);
|
|
265870
|
-
const
|
|
265871
|
-
|
|
265872
|
-
|
|
265873
|
-
|
|
265874
|
-
|
|
265875
|
-
|
|
266104
|
+
const retirement = new Retirement(async () => {
|
|
266105
|
+
try {
|
|
266106
|
+
await Promise.all([predecessor?.run(), controlClosed, this.waitForCleanup(record2)]);
|
|
266107
|
+
} catch (error2) {
|
|
266108
|
+
this.logger.debug(`Session preparation retirement failed: ${formatErrorMessage(error2)}`);
|
|
266109
|
+
throw error2;
|
|
266110
|
+
}
|
|
266111
|
+
if (this.retiring.get(record2.sessionId) === retirement) {
|
|
265876
266112
|
this.retiring.delete(record2.sessionId);
|
|
265877
266113
|
}
|
|
265878
266114
|
});
|
|
265879
|
-
|
|
265880
|
-
|
|
265881
|
-
|
|
265882
|
-
record2.retirementPromise = cleanup;
|
|
265883
|
-
this.retiring.set(record2.sessionId, cleanup);
|
|
266115
|
+
record2.retirement = retirement;
|
|
266116
|
+
this.retiring.set(record2.sessionId, retirement);
|
|
266117
|
+
const cleanup = retirement.run();
|
|
265884
266118
|
record2.abortController.abort();
|
|
265885
266119
|
return cleanup;
|
|
265886
266120
|
}
|
|
@@ -265888,17 +266122,26 @@ class SessionPreparationService {
|
|
|
265888
266122
|
if (record2.cleanupPromise) return record2.cleanupPromise;
|
|
265889
266123
|
const cleanup = Promise.resolve().then(() => resource.dispose());
|
|
265890
266124
|
void cleanup.catch((error2) => {
|
|
266125
|
+
if (record2.cleanupPromise === cleanup) record2.cleanupPromise = void 0;
|
|
265891
266126
|
this.logger.debug(`Failed to dispose session preparation: ${formatErrorMessage(error2)}`);
|
|
265892
266127
|
});
|
|
265893
266128
|
record2.cleanupPromise = cleanup;
|
|
265894
266129
|
return cleanup;
|
|
265895
266130
|
}
|
|
265896
266131
|
async waitForCleanup(record2) {
|
|
265897
|
-
|
|
265898
|
-
|
|
265899
|
-
|
|
265900
|
-
})
|
|
265901
|
-
|
|
266132
|
+
let resource;
|
|
266133
|
+
try {
|
|
266134
|
+
resource = await record2.resourcePromise;
|
|
266135
|
+
} catch (error2) {
|
|
266136
|
+
if (!(error2 instanceof SessionPreparationCleanupError)) return;
|
|
266137
|
+
if (record2.rollbackFailure !== error2 || !error2.retry) {
|
|
266138
|
+
record2.rollbackFailure = error2;
|
|
266139
|
+
throw error2;
|
|
266140
|
+
}
|
|
266141
|
+
await error2.retry();
|
|
266142
|
+
return;
|
|
266143
|
+
}
|
|
266144
|
+
await this.scheduleCleanup(record2, resource);
|
|
265902
266145
|
}
|
|
265903
266146
|
}
|
|
265904
266147
|
const SPECULATIVE_WORKTREE_MARKER_VERSION = 1;
|
|
@@ -266744,6 +266987,7 @@ class SessionManager extends EventEmitter {
|
|
|
266744
266987
|
let adoptionPromise = null;
|
|
266745
266988
|
let started = false;
|
|
266746
266989
|
let cleanupPromise = null;
|
|
266990
|
+
let sandboxCleanupFailed = false;
|
|
266747
266991
|
const initialized2 = createDeferred();
|
|
266748
266992
|
const sessionStart = createDeferred();
|
|
266749
266993
|
const workspaceReady = createDeferred();
|
|
@@ -266780,7 +267024,10 @@ class SessionManager extends EventEmitter {
|
|
|
266780
267024
|
await session2.terminate(true);
|
|
266781
267025
|
} else if (sandbox) {
|
|
266782
267026
|
await sandbox.terminate(true);
|
|
266783
|
-
|
|
267027
|
+
const recover = sandboxCleanupFailed ? sandbox.recoverCleanup?.bind(sandbox) : void 0;
|
|
267028
|
+
sandboxCleanupFailed = true;
|
|
267029
|
+
await (recover ? recover() : sandbox.cleanup());
|
|
267030
|
+
sandboxCleanupFailed = false;
|
|
266784
267031
|
}
|
|
266785
267032
|
} catch (error2) {
|
|
266786
267033
|
await credentials.release();
|
|
@@ -266801,7 +267048,8 @@ class SessionManager extends EventEmitter {
|
|
|
266801
267048
|
await rm(provisionalWorkdir, { recursive: true, force: true });
|
|
266802
267049
|
}
|
|
266803
267050
|
})().catch((error2) => {
|
|
266804
|
-
|
|
267051
|
+
cleanupPromise = null;
|
|
267052
|
+
throw new SessionPreparationCleanupError(error2, cleanup);
|
|
266805
267053
|
});
|
|
266806
267054
|
return cleanupPromise;
|
|
266807
267055
|
};
|
|
@@ -271971,7 +272219,7 @@ const createNodeServicesForLease = async (sessionDoc, lease) => {
|
|
|
271971
272219
|
};
|
|
271972
272220
|
}
|
|
271973
272221
|
};
|
|
271974
|
-
const { createRoostSessionData: createRoostSessionData2 } = await import("./chunks/index-
|
|
272222
|
+
const { createRoostSessionData: createRoostSessionData2 } = await import("./chunks/index-a0nEYQPa.js");
|
|
271975
272223
|
syncModelSummary = async () => {
|
|
271976
272224
|
const read2 = latestModelTurnId ? await history.readTurn(latestModelTurnId) : { state: "missing" };
|
|
271977
272225
|
const turn = read2.state === "ready" ? [read2.turn] : [];
|
|
@@ -306177,7 +306425,7 @@ async function runRender(file2, options2) {
|
|
|
306177
306425
|
}
|
|
306178
306426
|
data = parsed;
|
|
306179
306427
|
} else {
|
|
306180
|
-
const { resolveReviewBundle } = await import("./chunks/index-
|
|
306428
|
+
const { resolveReviewBundle } = await import("./chunks/index-DnWlNrUf.js");
|
|
306181
306429
|
const { collectBundleDiagnostics, hasErrorDiagnostics, createReviewBundleSnapshot } = await import("./chunks/index-DG2Ikd5A.js");
|
|
306182
306430
|
const bundle = await resolveReviewBundle({
|
|
306183
306431
|
reviewFilePath: inputPath,
|
|
@@ -306196,7 +306444,7 @@ async function runRender(file2, options2) {
|
|
|
306196
306444
|
data = createReviewBundleSnapshot(bundle);
|
|
306197
306445
|
}
|
|
306198
306446
|
const { injectReviewSnapshot } = await import("./chunks/index-BeRTvYK1.js");
|
|
306199
|
-
const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-
|
|
306447
|
+
const { resolveReviewViewerTemplate } = await import("./chunks/review-viewer-Cm1OZZZc.js");
|
|
306200
306448
|
const template = await resolveReviewViewerTemplate();
|
|
306201
306449
|
const html = injectReviewSnapshot(template, data);
|
|
306202
306450
|
const outputPath = options2.output ? path__default$1.resolve(options2.output) : defaultHtmlOutputPath(inputPath);
|