Merge origin/master: combine boot-owned settlement with the fail-loud release
Conflicts: apps/cli/src/tui.ts (keep the release install over master's comment rewording), packages/ui/app-boot/README* (master's new installFailLoud row wording plus this branch's release and timeout rows).
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
* from it, so `dsh` acts on whatever project it is launched in. Session storage
|
||||
* is the exception — it lives under the Harness home so `/resume` reaches every
|
||||
* workspace, and an in-place resume enters the selected session's own directory.
|
||||
* `dsh experimental-meta` is the one exception — it makes this harness
|
||||
* checkout the workspace. `dsh experimental-upgrade` is a fresh session whose
|
||||
* `dsh meta` is the one exception — it makes this harness
|
||||
* checkout the workspace. `dsh upgrade` is a fresh session whose
|
||||
* first turn auto-invokes a bundled skill. After boot, the agent's system
|
||||
* prompt is told the path to this harness checkout so it can find its own
|
||||
* source.
|
||||
@@ -28,8 +28,10 @@ import {
|
||||
loadOverlayPatches,
|
||||
loadPersonalPatches,
|
||||
resolveConfigPath,
|
||||
watchPersonalPatches,
|
||||
} from '@deepseek-ai/dsh-app-boot'
|
||||
import { resolveDshHome } from '@deepseek-ai/dsh-paths'
|
||||
import type { PatchOptions } from '@cordisjs/plugin-include'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import { configHasTelemetryRow, resolveTelemetryPatch } from './app-cli-entry.ts'
|
||||
import { SESSION_QUERY_SQLITE_PATH_KEY } from '@deepseek-ai/dsh-session-query-sqlite'
|
||||
@@ -71,7 +73,7 @@ const SESSION_QUERY_DB = `session-query-${String(process.pid)}-${randomUUID()}.d
|
||||
// The harness checkout root: three hops up from apps/cli/{src,lib}, resolved
|
||||
// from this bin's location so it holds however `dsh` is launched (a PATH
|
||||
// symlink, an arbitrary cwd). The agent is told where its own source lives.
|
||||
/** The harness checkout used as the `dsh experimental-meta` workspace and source prompt path. */
|
||||
/** The harness checkout used as the `dsh meta` workspace and source prompt path. */
|
||||
export const SOURCE_ROOT = fileURLToPath(new URL('../../..', import.meta.url))
|
||||
|
||||
/* v8 ignore start -- composition over the unit-tested dsh-app-boot helpers;
|
||||
@@ -88,9 +90,9 @@ export const SOURCE_ROOT = fileURLToPath(new URL('../../..', import.meta.url))
|
||||
* {@link CONFIGURED_AGENT_IDENTITIES_KEY}, so no config key selects the session
|
||||
* and an overlay replacing the agent row cannot drop it.
|
||||
* @param workspace - a directory to make the workspace instead of the invoking
|
||||
* one, or `undefined` to keep the cwd. Only `dsh experimental-meta` passes it.
|
||||
* one, or `undefined` to keep the cwd. Only `dsh meta` passes it.
|
||||
* @param initialSkill - a bundled skill to auto-invoke as a fresh session's
|
||||
* first turn, or `undefined`. Set only by `dsh experimental-upgrade` and
|
||||
* first turn, or `undefined`. Set only by `dsh upgrade` and
|
||||
* ignored on a resume, so it never re-fires; reaches the app through
|
||||
* {@link INITIAL_SKILL_KEY}.
|
||||
* @param configReplace - a config path to boot as the ENTIRE tree, bypassing the
|
||||
@@ -150,7 +152,7 @@ export async function runTui(
|
||||
installFailLoud(NAME, process, async () => {
|
||||
await app.current?.fiber.dispose()
|
||||
})
|
||||
// Resume always enters the default surface because experimental-meta rejects
|
||||
// Resume always enters the default surface because meta rejects
|
||||
// parent options, including `--resume`. The resumed session already persists
|
||||
// its cwd.
|
||||
const resumeArgs = (sessionId: string): string[] => [
|
||||
@@ -211,15 +213,16 @@ export async function runTui(
|
||||
// presence is checked against the tree actually booting, so a
|
||||
// --config-replace tree is judged on its own rows, not the shipped base's.
|
||||
const telemetryPatch = resolveTelemetryPatch(process.env.DSH_TELEMETRY_DISABLED, configHasTelemetryRow(bootConfig))
|
||||
const patches = [
|
||||
const composePatches = (personalPatches: PatchOptions[]): PatchOptions[] => [
|
||||
...replaceTree ? [] : [
|
||||
...loadOverlayPatches(NAME, TUI_OVERLAY),
|
||||
...resolvedConfig === undefined
|
||||
? loadPersonalPatches(NAME) ?? []
|
||||
? personalPatches
|
||||
: loadOverlayPatches(NAME, resolveConfigPath(resolvedConfig, undefined)),
|
||||
],
|
||||
...telemetryPatch === undefined ? [] : [telemetryPatch],
|
||||
]
|
||||
const patches = composePatches(loadPersonalPatches(NAME) ?? [])
|
||||
const queryIndexPath = join(tmpdir(), SESSION_QUERY_DB)
|
||||
const ctx = await boot(
|
||||
NAME,
|
||||
@@ -260,6 +263,14 @@ export async function runTui(
|
||||
}
|
||||
},
|
||||
)
|
||||
// The shipped tree includes HMR and keeps personal config live. An explicit
|
||||
// --config tree replaces the personal overlay (so there is nothing to keep
|
||||
// live), and a --config-replace or HMR-less tree remains a valid composition
|
||||
// that still receives the startup overlay but deliberately has no hidden
|
||||
// watcher.
|
||||
if (resolvedConfig === undefined && !replaceTree && ctx.get('hmr') !== undefined) {
|
||||
await watchPersonalPatches(ctx, { binName: NAME, compose: composePatches })
|
||||
}
|
||||
app.current = ctx
|
||||
addHarnessSourceSection(ctx, SOURCE_ROOT)
|
||||
if (showFirstRunWelcome) {
|
||||
|
||||
Reference in New Issue
Block a user