mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
* feat: attach files to a flow chat message Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: store chat uploads under windmill_uploads and withdraw refused sends cleanly Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: refuse extra files for a single-file input and keep attachments on retry Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: clean up partial upload batches, withdraw a stopped send once, free retry payloads Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: list a chat conversation only once its run starts and require files where the flow does Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat: carry uploaded attachments on the pending chat user message Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: route rich-composer file paste through the attachment lanes and tighten comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: keep a stopped turn's files for retry and let an explicit media type win Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: refuse chat attachments sent without text and shorten comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: resolve the attachments input from real flow input reads, ignoring loop iteration Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: read flow input references through one parser for the model and attachments controls Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: withdraw an attachment send stopped after its uploads answered Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: discard uploads when a send is stopped as its attachments are announced Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: keep uploadAttachments' doc comment on uploadAttachments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * refactor: never delete chat uploads from workspace storage Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: pin that a failed upload aborts the rest of its batch Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
import { CancelError, WorkspaceService, type LargeFileStorage } from '$lib/gen'
|
|
import { resource } from 'runed'
|
|
|
|
/**
|
|
* Whether the workspace has large-file storage the upload endpoints can resolve. Every
|
|
* kind counts, not only S3: Azure Blob, Azure Workload Identity, S3 via AWS OIDC and GCS
|
|
* all go through the same object-store abstraction, so reading `s3_resource_path` alone
|
|
* calls a perfectly good workspace unconfigured.
|
|
*/
|
|
function storageConfigured(storage: LargeFileStorage | undefined): boolean {
|
|
if (!storage) return false
|
|
return (
|
|
storage.type !== undefined ||
|
|
storage.s3_resource_path !== undefined ||
|
|
storage.azure_blob_resource_path !== undefined ||
|
|
storage.gcs_resource_path !== undefined
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Whether the workspace can store uploaded files; read `.current`. Assumed configured until
|
|
* this workspace's own answer lands, so "no storage" never flashes on navigation or shows
|
|
* merely because the fetch failed.
|
|
*/
|
|
export function useWorkspaceStorageConfigured(ws: () => string | undefined): {
|
|
readonly current: boolean
|
|
} {
|
|
const settings = resource(ws, async (ws, _previousWs, { onCleanup }) => {
|
|
if (!ws) return undefined
|
|
const req = WorkspaceService.getPublicSettings({ workspace: ws })
|
|
// `resource` keeps whatever lands last: cancel a superseded request so a slow
|
|
// reply for a workspace we have left cannot overwrite the current one.
|
|
onCleanup(() => req.cancel())
|
|
try {
|
|
return { ws, settings: await req }
|
|
} catch (err) {
|
|
if (!(err instanceof CancelError)) {
|
|
console.error('Failed to fetch workspace settings:', err)
|
|
}
|
|
return undefined
|
|
}
|
|
})
|
|
|
|
const configured = $derived.by(() => {
|
|
const loaded = settings.current
|
|
return loaded && loaded.ws === ws()
|
|
? storageConfigured(loaded.settings.large_file_storage)
|
|
: true
|
|
})
|
|
|
|
return {
|
|
get current() {
|
|
return configured
|
|
}
|
|
}
|
|
}
|