diff --git a/frontend/src/agents/workflow/WorkflowBuilder.tsx b/frontend/src/agents/workflow/WorkflowBuilder.tsx
index dfa4e532..82c5f518 100644
--- a/frontend/src/agents/workflow/WorkflowBuilder.tsx
+++ b/frontend/src/agents/workflow/WorkflowBuilder.tsx
@@ -85,6 +85,7 @@ import {
getDocumentsMode,
normalizeFilePassing,
toDocumentVariableOptions,
+ withChosenDocumentOptions,
} from './documentConfig';
import {
AgentNode,
@@ -2271,9 +2272,10 @@ function WorkflowBuilderInner() {
{documentsMode === 'choose' && (
setInputDocuments(
diff --git a/frontend/src/agents/workflow/documentConfig.test.ts b/frontend/src/agents/workflow/documentConfig.test.ts
index 4ded092c..320c645f 100644
--- a/frontend/src/agents/workflow/documentConfig.test.ts
+++ b/frontend/src/agents/workflow/documentConfig.test.ts
@@ -9,6 +9,7 @@ import {
normalizeFilePassing,
stripAgentPrefix,
toDocumentVariableOptions,
+ withChosenDocumentOptions,
} from './documentConfig';
describe('getDocumentsMode', () => {
@@ -124,3 +125,38 @@ describe('toDocumentVariableOptions', () => {
expect(options).toEqual([{ value: 'wire_doc', label: 'wire_doc' }]);
});
});
+
+describe('withChosenDocumentOptions', () => {
+ const base = [{ value: 'wire_doc', label: 'wire_doc' }];
+
+ it('keeps known options unchanged when all chosen are present', () => {
+ expect(withChosenDocumentOptions(base, ['wire_doc'])).toEqual(base);
+ });
+
+ it('appends an orphaned chosen name (renamed/deleted upstream var) as removable', () => {
+ expect(
+ withChosenDocumentOptions(base, ['wire_doc', 'renamed_doc']),
+ ).toEqual([
+ { value: 'wire_doc', label: 'wire_doc' },
+ { value: 'renamed_doc', label: 'renamed_doc' },
+ ]);
+ });
+
+ it('surfaces a literal ref that has no upstream option', () => {
+ expect(withChosenDocumentOptions([], ['A1'])).toEqual([
+ { value: 'A1', label: 'A1' },
+ ]);
+ });
+
+ it('ignores blanks and the wildcard token', () => {
+ expect(
+ withChosenDocumentOptions(base, ['', ' ', ALL_INPUT_DOCUMENTS_TOKEN]),
+ ).toEqual(base);
+ });
+
+ it('does not duplicate an already-known chosen name', () => {
+ expect(withChosenDocumentOptions(base, ['wire_doc', 'wire_doc'])).toEqual(
+ base,
+ );
+ });
+});
diff --git a/frontend/src/agents/workflow/documentConfig.ts b/frontend/src/agents/workflow/documentConfig.ts
index daf57971..9cda0bcf 100644
--- a/frontend/src/agents/workflow/documentConfig.ts
+++ b/frontend/src/agents/workflow/documentConfig.ts
@@ -82,3 +82,21 @@ export function toDocumentVariableOptions(
}
return options;
}
+
+/** Append stored chosen names lacking an upstream option so they stay visible and removable. */
+export function withChosenDocumentOptions(
+ options: { value: string; label: string }[],
+ chosen: string[],
+): { value: string; label: string }[] {
+ const known = new Set(options.map((option) => option.value));
+ const merged = [...options];
+ for (const name of chosen) {
+ const value = name.trim();
+ if (!value || value === ALL_INPUT_DOCUMENTS_TOKEN || known.has(value)) {
+ continue;
+ }
+ known.add(value);
+ merged.push({ value, label: value });
+ }
+ return merged;
+}