fix: address ds-review-bot v8 findings
- llm-deepseek: the uncatalogued resolveModel fallback declares text-only modalities — the wire route is text-only regardless of catalog membership, so "unknown" must not let the host persist-then-fail images. - session.selectModel also consults the pending-inbox mirror: a queued image prompt enters the log only when claimed, after a switch would land. - attachment store: ensureDurableDirectory syncs every ancestor entry up to a caller-vouched boundary regardless of what mkdir reports — a raced "already existed" is not "already durable". - One image walker (imageBlockIn/imageInEvent) now serves both attachment authorization and the selection gate; referencedImage therefore also authorizes references inside wrapped message content. - InputHub: the scope disposer resolves the conversation service optionally (teardown/HMR must reach quiescence), and a send failing after its scope died releases the in-flight drafts instead of restoring them onto a disposed shell. - http-bridge destroys declared-oversize requests with connection: close instead of draining a body the client can trickle indefinitely. - LlmService validates AND detaches modality arrays identically on the advisory and exact routes; READMEs record the fourth INVALID_MODEL_INFO rejection reason. - CLI provider docs (JSDoc, README pair, Agent Note pair) describe the reuse behavior; llm-route.spec now parses the SHIPPED cordis.yml through the production extraction, pinning the row coupling. - image-display lane pins gallery/rail shape in inline snapshots and the object-URL scheme this environment must take; stale host.schema comment dropped.
This commit is contained in:
@@ -87,11 +87,17 @@ export class InputHub implements InputService {
|
||||
for (const off of offs) off()
|
||||
// Draft attachments die with the scope: the shell only holds ids, so
|
||||
// the service-owned File objects and object URLs must be released
|
||||
// here or they leak for the page lifetime.
|
||||
// here or they leak for the page lifetime. The lookup is optional —
|
||||
// during application teardown or HMR of this plugin the root
|
||||
// `conversation` service can already be unregistered while session
|
||||
// scopes are still alive; a throwing disposer would abort teardown
|
||||
// quiescence, and the service's own disposal effect revokes every
|
||||
// remaining URL in that case anyway.
|
||||
const drafts = shell.snapshot.imageIds
|
||||
shell.dispose()
|
||||
this.shells.delete(id)
|
||||
for (const imageId of drafts) this.conversation().releaseDraftImage(imageId)
|
||||
const conversation = this.rootCtx.get('conversation') as ConversationAttachmentFace | undefined
|
||||
for (const imageId of drafts) conversation?.releaseDraftImage(imageId)
|
||||
}
|
||||
}, 'conversation.input: session shell')
|
||||
return shell
|
||||
@@ -139,8 +145,18 @@ export class InputHub implements InputService {
|
||||
// Commit, not an editable clear: undo must not resurrect sent content.
|
||||
shell?.commitSend(imageIds)
|
||||
void this.conversation().sendSession(session, text, mode, imageIds).catch(() => {
|
||||
shell?.restoreImages(imageIds)
|
||||
if (shell?.snapshot.draft === '') shell.setDraft(text)
|
||||
// Restore only into the shell that still owns the session: if the scope
|
||||
// died while the send was in flight, `commitSend` already removed the
|
||||
// ids from the (now disposed) shell, so the teardown release could not
|
||||
// see them — release the drafts here instead of resurrecting them onto
|
||||
// a dead instance where they would leak for the page lifetime.
|
||||
if (this.shells.get(session.sessionId) === shell) {
|
||||
shell?.restoreImages(imageIds)
|
||||
if (shell?.snapshot.draft === '') shell.setDraft(text)
|
||||
return
|
||||
}
|
||||
const conversation = this.rootCtx.get('conversation') as ConversationAttachmentFace | undefined
|
||||
for (const id of imageIds) conversation?.releaseDraftImage(id)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user