mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
fix: client module loader report package resolve info
This commit is contained in:
@@ -58,6 +58,40 @@ interface PkgMeta {
|
||||
immediately: boolean
|
||||
}
|
||||
|
||||
/** Missing built client export, retained as structured data for activation-error grouping. */
|
||||
class MissingClientBundleError extends Error {
|
||||
constructor(
|
||||
readonly packageName: string,
|
||||
readonly clientPath: string,
|
||||
cause: unknown,
|
||||
) {
|
||||
super(
|
||||
`client-modules: ${packageName} needs to be built before source launch; client bundle not found at ${clientPath}`,
|
||||
{ cause },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Activation failures grouped by actionable package-build errors and unrelated failures. */
|
||||
class ClientPackageCompositionError extends AggregateError {
|
||||
constructor(failures: Error[]) {
|
||||
const missingBundles = failures.filter((error): error is MissingClientBundleError => error instanceof MissingClientBundleError)
|
||||
const otherFailures = failures.filter(error => !(error instanceof MissingClientBundleError))
|
||||
const packageNoun = failures.length === 1 ? 'package' : 'packages'
|
||||
const lines = [`client-modules: ${String(failures.length)} client ${packageNoun} failed to compose:`]
|
||||
if (missingBundles.length > 0) {
|
||||
lines.push(' client packages requiring a build before source launch:')
|
||||
for (const error of missingBundles) {
|
||||
lines.push(` - package: ${error.packageName}`, ` path: ${error.clientPath}`)
|
||||
}
|
||||
}
|
||||
if (otherFailures.length > 0) {
|
||||
lines.push(' other failures:', ...otherFailures.map(error => ` - ${error.message}`))
|
||||
}
|
||||
super(failures, lines.join('\n'))
|
||||
}
|
||||
}
|
||||
|
||||
/** One composed table row: the wire entry plus its bundle path. */
|
||||
interface WebPluginRecord {
|
||||
entry: WebBootEntry
|
||||
@@ -138,7 +172,7 @@ export function injectBootManifest(html: string, graph: WebBootGraph): string {
|
||||
* + bundle route + index tap. Construction runs the activation scan
|
||||
* synchronously — a malformed declaration or missing bundle among the
|
||||
* already-loaded entries aggregates into one loud throw (FAILED fiber; the
|
||||
* boot sweep reports it).
|
||||
* boot activation audit reports it).
|
||||
*/
|
||||
export class ClientModuleHostService extends Service {
|
||||
static inject = ['httpServer', 'loader']
|
||||
@@ -194,10 +228,7 @@ export class ClientModuleHostService extends Service {
|
||||
const failures: Error[] = []
|
||||
this.flush(err => failures.push(err))
|
||||
if (failures.length > 0) {
|
||||
throw new AggregateError(
|
||||
failures,
|
||||
`client-modules: ${String(failures.length)} client package(s) failed to compose:\n${failures.map(e => ` - ${e.message}`).join('\n')}`,
|
||||
)
|
||||
throw new ClientPackageCompositionError(failures)
|
||||
}
|
||||
|
||||
ctx.effect(
|
||||
@@ -322,6 +353,16 @@ export class ClientModuleHostService extends Service {
|
||||
return meta
|
||||
}
|
||||
|
||||
/** Read the activation-time bundle revision, translating only a missing build artifact into source-launch guidance. */
|
||||
private initialBundleRevision(pkgName: string, clientPath: string): string {
|
||||
try {
|
||||
return shortHash(readFileSync(clientPath))
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error
|
||||
throw new MissingClientBundleError(pkgName, clientPath, error)
|
||||
}
|
||||
}
|
||||
|
||||
/** Reconcile one entry name against the live loader entries. @returns whether the table changed. */
|
||||
private processOne(entryName: string): boolean {
|
||||
let qualifies = false
|
||||
@@ -337,7 +378,7 @@ export class ClientModuleHostService extends Service {
|
||||
if (meta === null) return false
|
||||
// The rev rides the row from here on: a fiber restart reuses the row (and
|
||||
// its rev) untouched; only rebuilt() re-reads the bundle.
|
||||
const rev = shortHash(readFileSync(meta.clientPath))
|
||||
const rev = this.initialBundleRevision(entryName, meta.clientPath)
|
||||
this.table.set(entryName, { entry: graphRow(entryName, rev, meta.inject, meta.immediately), clientPath: meta.clientPath })
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user