@workflow-code/cli 0.2.4-20261011004.codex-cli-web → 0.2.4-20261011006.codex-cli-web

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -74,6 +74,8 @@ try {
74
74
  createLocalWorkflowKVStore, createWorkflowKVContext, createWorkflowPersistentValueContext,
75
75
  listLocalWorkflowKVEntries, deleteLocalWorkflowKVEntry, getKnowledgeDocument, listKnowledgeDocuments,
76
76
  } = await import(coreUrl);
77
+ const core = await import(coreUrl);
78
+ const { readKanbanProjectInfo, runKanbanDataCall } = await import(new URL(import.meta.url.includes('/src/web/') ? './kanban-data.ts' : './kanban-data.mjs', import.meta.url));
77
79
  if (request.method === 'inspect') {
78
80
  const projects = [];
79
81
  const errors = [];
@@ -95,6 +97,8 @@ try {
95
97
  diagnostics: structure.diagnostics,
96
98
  defaultEntrypoint: structure.defaultEntrypoint,
97
99
  artifactEntry: structure.kanban ? createKanbanArtifactEntryPath(structure.kanban) : undefined,
100
+ kanban: structure.kanban ? { artifactDir: structure.kanban.artifactDir, entry: structure.kanban.entry } : undefined,
101
+ projectInfo: structure.kanban ? readKanbanProjectInfo(pkg) : undefined,
98
102
  conversation: structure.conversation,
99
103
  requiresLogin: await requiresSystemAi(folderPath),
100
104
  });
@@ -138,7 +142,9 @@ try {
138
142
  const reference = JSON.parse(await readFile(path.join(filesDir, id, 'metadata.json'), 'utf8'));
139
143
  return { reference, path: reference.path };
140
144
  };
141
- if (request.method === 'resolve') {
145
+ if (request.method === 'kanban-bridge') {
146
+ send('result', await runKanbanDataCall(core, request.project, request.storageDir, request.call));
147
+ } else if (request.method === 'resolve') {
142
148
  send('result', await resolveLocalWorkflowParams({
143
149
  workflowDir: request.project.folderPath,
144
150
  entrypointId: request.entrypointId,
@@ -1238,6 +1238,29 @@ main {
1238
1238
  overflow: auto;
1239
1239
  padding: 16px;
1240
1240
  }
1241
+ .action-dialog {
1242
+ width: min(380px, calc(100vw - 32px));
1243
+ }
1244
+ .action-dialog label {
1245
+ display: grid;
1246
+ gap: 8px;
1247
+ }
1248
+ .action-dialog input {
1249
+ width: 100%;
1250
+ min-width: 0;
1251
+ padding: 8px;
1252
+ color: inherit;
1253
+ background: var(--vscode-input-background);
1254
+ border: 1px solid var(--border);
1255
+ border-radius: 4px;
1256
+ }
1257
+ .action-dialog .prompt-navigation {
1258
+ justify-content: flex-end;
1259
+ margin-top: 16px;
1260
+ }
1261
+ .action-dialog .danger {
1262
+ color: var(--vscode-errorForeground);
1263
+ }
1241
1264
  .permissions-table {
1242
1265
  width: 100%;
1243
1266
  border-collapse: collapse;
@@ -1890,10 +1913,25 @@ textarea::placeholder {
1890
1913
  overflow-wrap: anywhere;
1891
1914
  }
1892
1915
  @media (max-width: 680px) {
1916
+ .project-menu {
1917
+ position: relative;
1918
+ }
1919
+ .project-menu .menu-heading {
1920
+ padding-right: 52px;
1921
+ }
1893
1922
  .web-account {
1894
- margin: 0 8px 4px;
1895
- min-height: 36px;
1896
- padding: 6px 10px;
1923
+ position: absolute;
1924
+ right: 10px;
1925
+ top: 6px;
1926
+ margin: 0;
1927
+ width: 28px;
1928
+ height: 28px;
1929
+ min-height: 28px;
1930
+ padding: 2px;
1931
+ border: 0;
1932
+ }
1933
+ .web-account-name {
1934
+ display: none;
1897
1935
  }
1898
1936
  }
1899
1937
  @media (max-width: 420px) {
@@ -2681,6 +2681,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
2681
2681
  const id = value.match(/(?:^|[/?#])(wf_[a-f0-9]{32})(?:$|[/?#])/i)?.[1];
2682
2682
  return files.find((file) => file.id === id || value === file.path || value === file.url || value === `file://${file.path}`);
2683
2683
  }
2684
+ function mediaUrl(source, kind, files, baseUrl) {
2685
+ const file = managedFileForUrl(source, files);
2686
+ const preview = file?.previewUrl ?? source;
2687
+ if (new RegExp(`^data:${kind}/[a-z0-9.+-]+;base64,`, "i").test(preview)) {
2688
+ return preview;
2689
+ }
2690
+ try {
2691
+ const url = file?.previewUrl ? new URL(preview, baseUrl) : new URL(preview);
2692
+ if (url.protocol === "http:" || url.protocol === "https:") {
2693
+ return url.href;
2694
+ }
2695
+ } catch {
2696
+ }
2697
+ return void 0;
2698
+ }
2684
2699
  function markdownHtml(text3, files = []) {
2685
2700
  const renderer = new d.Renderer();
2686
2701
  renderer.image = (token) => {
@@ -3854,9 +3869,8 @@ ${JSON.stringify(output.details, null, 2)}` : "");
3854
3869
  summary.innerHTML = `${iconHtml(status === "running" ? "loading" : status === "failed" ? "error" : status === "success" ? "check" : "chevron-right")}<span>${escapeHtml(content?.tool ?? item.title ?? "\u8BE6\u60C5")}</span>`;
3855
3870
  root.append(summary);
3856
3871
  if (["audio", "video"].includes(item.contentType ?? "") && typeof content?.src === "string") {
3857
- const file = managedFileForUrl(content.src, files);
3858
- const src = file?.previewUrl ?? content.src;
3859
- if (/^https?:\/\//i.test(src) || new RegExp(`^data:${item.contentType}/[a-z0-9.+-]+;base64,`, "i").test(src)) {
3872
+ const src = mediaUrl(content.src, item.contentType === "audio" ? "audio" : "video", files, location.href);
3873
+ if (src) {
3860
3874
  const media = document.createElement(item.contentType === "audio" ? "audio" : "video");
3861
3875
  media.controls = true;
3862
3876
  media.preload = "metadata";
@@ -4133,6 +4147,7 @@ ${state.user?.avatarUrl ?? ""}`;
4133
4147
  }, { once: true });
4134
4148
  }
4135
4149
  emit;
4150
+ clientId = crypto.randomUUID();
4136
4151
  source;
4137
4152
  banner;
4138
4153
  connecting;
@@ -4199,7 +4214,9 @@ ${state.user?.avatarUrl ?? ""}`;
4199
4214
  if (!session.ok) {
4200
4215
  throw new Error("Cannot connect to the project.");
4201
4216
  }
4202
- const source = this.source = new EventSource(this.fileUrl("/api/events"));
4217
+ const eventsUrl = new URL(this.fileUrl("/api/events"), location.href);
4218
+ eventsUrl.searchParams.set("clientId", this.clientId);
4219
+ const source = this.source = new EventSource(eventsUrl.href);
4203
4220
  source.onopen = () => {
4204
4221
  this.attempts = 0;
4205
4222
  this.update("connected");
@@ -4232,7 +4249,8 @@ ${state.user?.avatarUrl ?? ""}`;
4232
4249
  }
4233
4250
  let response;
4234
4251
  try {
4235
- response = await fetch("/api/message", { method: "POST", headers: { ...this.headers(), "Content-Type": "application/json" }, body: JSON.stringify(message) });
4252
+ const body = ["kanban-method-state", "kanban-method-reply"].includes(message.type) ? { ...message, clientId: this.clientId } : message;
4253
+ response = await fetch("/api/message", { method: "POST", headers: { ...this.headers(), "Content-Type": "application/json" }, body: JSON.stringify(body) });
4236
4254
  } catch {
4237
4255
  this.interrupted();
4238
4256
  throw new ConnectionError("\u8FDE\u63A5\u5DF2\u4E2D\u65AD\u3002");
@@ -4274,6 +4292,66 @@ ${state.user?.avatarUrl ?? ""}`;
4274
4292
  }
4275
4293
  };
4276
4294
 
4295
+ // src/web/ui/action-dialog.ts
4296
+ function requestAction(options) {
4297
+ return new Promise((resolve) => {
4298
+ const dialog = document.createElement("dialog");
4299
+ dialog.className = "conversation-dialog action-dialog";
4300
+ const title = document.createElement("h2");
4301
+ title.id = `action-${crypto.randomUUID()}`;
4302
+ title.textContent = options.title;
4303
+ dialog.setAttribute("aria-labelledby", title.id);
4304
+ const header = document.createElement("header");
4305
+ header.append(title, iconButton("close", "\u5173\u95ED", () => dialog.close()));
4306
+ const form = document.createElement("form");
4307
+ form.className = "dialog-body";
4308
+ let input, result;
4309
+ if (options.label) {
4310
+ const label = document.createElement("label");
4311
+ label.textContent = options.label;
4312
+ input = document.createElement("input");
4313
+ input.type = "text";
4314
+ input.required = true;
4315
+ input.autofocus = true;
4316
+ input.value = options.value ?? "";
4317
+ label.append(input);
4318
+ form.append(label);
4319
+ }
4320
+ const actions = document.createElement("div");
4321
+ actions.className = "prompt-navigation";
4322
+ const cancel = document.createElement("button");
4323
+ cancel.type = "button";
4324
+ cancel.className = "prompt-button";
4325
+ cancel.textContent = "\u53D6\u6D88";
4326
+ cancel.onclick = () => dialog.close();
4327
+ const confirm = document.createElement("button");
4328
+ confirm.type = "submit";
4329
+ confirm.className = "prompt-button";
4330
+ confirm.textContent = options.confirm;
4331
+ if (options.danger) {
4332
+ confirm.classList.add("danger");
4333
+ }
4334
+ actions.append(cancel, confirm);
4335
+ form.append(actions);
4336
+ dialog.append(header, form);
4337
+ form.onsubmit = (event) => {
4338
+ event.preventDefault();
4339
+ if (input && !input.value.trim()) {
4340
+ input.focus();
4341
+ return;
4342
+ }
4343
+ result = input?.value.trim() ?? "";
4344
+ dialog.close();
4345
+ };
4346
+ dialog.addEventListener("close", () => {
4347
+ dialog.remove();
4348
+ resolve(result);
4349
+ }, { once: true });
4350
+ document.body.append(dialog);
4351
+ dialog.showModal();
4352
+ });
4353
+ }
4354
+
4277
4355
  // src/web/ui/host.ts
4278
4356
  function acquireWorkflowHost() {
4279
4357
  const embedded = globalThis.acquireVsCodeApi;
@@ -4376,7 +4454,7 @@ ${state.user?.avatarUrl ?? ""}`;
4376
4454
  accountPanel = new AccountPanel(document.querySelector("#project-menu"), request);
4377
4455
  });
4378
4456
  return {
4379
- postMessage: (message) => {
4457
+ postMessage: async (message) => {
4380
4458
  if (message.type === "ready") {
4381
4459
  return;
4382
4460
  }
@@ -4389,13 +4467,13 @@ ${state.user?.avatarUrl ?? ""}`;
4389
4467
  return;
4390
4468
  }
4391
4469
  if (message.type === "session-action" && message.action === "rename") {
4392
- const title = prompt("\u5BF9\u8BDD\u540D\u79F0");
4393
- if (!title) {
4470
+ const title = await requestAction({ title: "\u91CD\u547D\u540D\u5BF9\u8BDD", label: "\u5BF9\u8BDD\u540D\u79F0", value: message.currentTitle, confirm: "\u4FDD\u5B58" });
4471
+ if (title === void 0) {
4394
4472
  return;
4395
4473
  }
4396
4474
  message = { ...message, title };
4397
4475
  }
4398
- if (message.type === "session-action" && message.action === "delete" && !confirm("\u5220\u9664\u8FD9\u4E2A\u5BF9\u8BDD\uFF1F")) {
4476
+ if (message.type === "session-action" && message.action === "delete" && await requestAction({ title: "\u5220\u9664\u8FD9\u4E2A\u5BF9\u8BDD\uFF1F", confirm: "\u5220\u9664", danger: true }) === void 0) {
4399
4477
  return;
4400
4478
  }
4401
4479
  if (message.type === "open-file") {
@@ -5446,7 +5524,7 @@ ${state.user?.avatarUrl ?? ""}`;
5446
5524
  const id = sessionMenuId;
5447
5525
  closeSessionMenu(true);
5448
5526
  if (id) {
5449
- post({ type: "session-action", id, action: button.dataset.action });
5527
+ post({ type: "session-action", id, action: button.dataset.action, currentTitle: state?.sessions.find((session) => session.id === id)?.title });
5450
5528
  }
5451
5529
  });
5452
5530
  }
@@ -5602,11 +5680,11 @@ ${state.user?.avatarUrl ?? ""}`;
5602
5680
  } else if (message.type === "attachments" && state && message.projectUri === state.project.uri && message.sessionId === state.activeId) {
5603
5681
  uploading = Math.max(0, uploading - 1);
5604
5682
  if (message.messageId) {
5605
- const prompt2 = messages.get(message.messageId)?.prompt;
5606
- if (prompt2 && prompt2.request.requestId === message.requestId) {
5607
- const field = prompt2.request.params.find((field2) => field2.name === message.paramName);
5683
+ const prompt = messages.get(message.messageId)?.prompt;
5684
+ if (prompt && prompt.request.requestId === message.requestId) {
5685
+ const field = prompt.request.params.find((field2) => field2.name === message.paramName);
5608
5686
  if (field) {
5609
- prompt2.fileValue(field.name, JSON.stringify((field.multiple ? message.files : message.files.slice(0, 1)).map(({ previewUrl: _2, ...file }) => file)));
5687
+ prompt.fileValue(field.name, JSON.stringify((field.multiple ? message.files : message.files.slice(0, 1)).map(({ previewUrl: _2, ...file }) => file)));
5610
5688
  }
5611
5689
  }
5612
5690
  } else if (message.paramName && fields.has(message.paramName)) {
@@ -1238,6 +1238,29 @@ main {
1238
1238
  overflow: auto;
1239
1239
  padding: 16px;
1240
1240
  }
1241
+ .action-dialog {
1242
+ width: min(380px, calc(100vw - 32px));
1243
+ }
1244
+ .action-dialog label {
1245
+ display: grid;
1246
+ gap: 8px;
1247
+ }
1248
+ .action-dialog input {
1249
+ width: 100%;
1250
+ min-width: 0;
1251
+ padding: 8px;
1252
+ color: inherit;
1253
+ background: var(--vscode-input-background);
1254
+ border: 1px solid var(--border);
1255
+ border-radius: 4px;
1256
+ }
1257
+ .action-dialog .prompt-navigation {
1258
+ justify-content: flex-end;
1259
+ margin-top: 16px;
1260
+ }
1261
+ .action-dialog .danger {
1262
+ color: var(--vscode-errorForeground);
1263
+ }
1241
1264
  .permissions-table {
1242
1265
  width: 100%;
1243
1266
  border-collapse: collapse;
@@ -2298,10 +2321,25 @@ textarea::placeholder {
2298
2321
  overflow-wrap: anywhere;
2299
2322
  }
2300
2323
  @media (max-width: 680px) {
2324
+ .project-menu {
2325
+ position: relative;
2326
+ }
2327
+ .project-menu .menu-heading {
2328
+ padding-right: 52px;
2329
+ }
2301
2330
  .web-account {
2302
- margin: 0 8px 4px;
2303
- min-height: 36px;
2304
- padding: 6px 10px;
2331
+ position: absolute;
2332
+ right: 10px;
2333
+ top: 6px;
2334
+ margin: 0;
2335
+ width: 28px;
2336
+ height: 28px;
2337
+ min-height: 28px;
2338
+ padding: 2px;
2339
+ border: 0;
2340
+ }
2341
+ .web-account-name {
2342
+ display: none;
2305
2343
  }
2306
2344
  }
2307
2345
  @media (max-width: 420px) {
@@ -5737,6 +5737,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
5737
5737
  const id = value.match(/(?:^|[/?#])(wf_[a-f0-9]{32})(?:$|[/?#])/i)?.[1];
5738
5738
  return files.find((file) => file.id === id || value === file.path || value === file.url || value === `file://${file.path}`);
5739
5739
  }
5740
+ function mediaUrl(source, kind, files, baseUrl) {
5741
+ const file = managedFileForUrl(source, files);
5742
+ const preview = file?.previewUrl ?? source;
5743
+ if (new RegExp(`^data:${kind}/[a-z0-9.+-]+;base64,`, "i").test(preview)) {
5744
+ return preview;
5745
+ }
5746
+ try {
5747
+ const url = file?.previewUrl ? new URL(preview, baseUrl) : new URL(preview);
5748
+ if (url.protocol === "http:" || url.protocol === "https:") {
5749
+ return url.href;
5750
+ }
5751
+ } catch {
5752
+ }
5753
+ return void 0;
5754
+ }
5740
5755
  function markdownHtml(text3, files = []) {
5741
5756
  const renderer = new d.Renderer();
5742
5757
  renderer.image = (token) => {
@@ -5986,6 +6001,7 @@ ${state2.user?.avatarUrl ?? ""}`;
5986
6001
  }, { once: true });
5987
6002
  }
5988
6003
  emit;
6004
+ clientId = crypto.randomUUID();
5989
6005
  source;
5990
6006
  banner;
5991
6007
  connecting;
@@ -6052,7 +6068,9 @@ ${state2.user?.avatarUrl ?? ""}`;
6052
6068
  if (!session.ok) {
6053
6069
  throw new Error("Cannot connect to the project.");
6054
6070
  }
6055
- const source = this.source = new EventSource(this.fileUrl("/api/events"));
6071
+ const eventsUrl = new URL(this.fileUrl("/api/events"), location.href);
6072
+ eventsUrl.searchParams.set("clientId", this.clientId);
6073
+ const source = this.source = new EventSource(eventsUrl.href);
6056
6074
  source.onopen = () => {
6057
6075
  this.attempts = 0;
6058
6076
  this.update("connected");
@@ -6085,7 +6103,8 @@ ${state2.user?.avatarUrl ?? ""}`;
6085
6103
  }
6086
6104
  let response;
6087
6105
  try {
6088
- response = await fetch("/api/message", { method: "POST", headers: { ...this.headers(), "Content-Type": "application/json" }, body: JSON.stringify(message) });
6106
+ const body = ["kanban-method-state", "kanban-method-reply"].includes(message.type) ? { ...message, clientId: this.clientId } : message;
6107
+ response = await fetch("/api/message", { method: "POST", headers: { ...this.headers(), "Content-Type": "application/json" }, body: JSON.stringify(body) });
6089
6108
  } catch {
6090
6109
  this.interrupted();
6091
6110
  throw new ConnectionError("\u8FDE\u63A5\u5DF2\u4E2D\u65AD\u3002");
@@ -6127,6 +6146,66 @@ ${state2.user?.avatarUrl ?? ""}`;
6127
6146
  }
6128
6147
  };
6129
6148
 
6149
+ // src/web/ui/action-dialog.ts
6150
+ function requestAction(options) {
6151
+ return new Promise((resolve2) => {
6152
+ const dialog = document.createElement("dialog");
6153
+ dialog.className = "conversation-dialog action-dialog";
6154
+ const title = document.createElement("h2");
6155
+ title.id = `action-${crypto.randomUUID()}`;
6156
+ title.textContent = options.title;
6157
+ dialog.setAttribute("aria-labelledby", title.id);
6158
+ const header = document.createElement("header");
6159
+ header.append(title, iconButton("close", "\u5173\u95ED", () => dialog.close()));
6160
+ const form = document.createElement("form");
6161
+ form.className = "dialog-body";
6162
+ let input, result;
6163
+ if (options.label) {
6164
+ const label = document.createElement("label");
6165
+ label.textContent = options.label;
6166
+ input = document.createElement("input");
6167
+ input.type = "text";
6168
+ input.required = true;
6169
+ input.autofocus = true;
6170
+ input.value = options.value ?? "";
6171
+ label.append(input);
6172
+ form.append(label);
6173
+ }
6174
+ const actions = document.createElement("div");
6175
+ actions.className = "prompt-navigation";
6176
+ const cancel = document.createElement("button");
6177
+ cancel.type = "button";
6178
+ cancel.className = "prompt-button";
6179
+ cancel.textContent = "\u53D6\u6D88";
6180
+ cancel.onclick = () => dialog.close();
6181
+ const confirm = document.createElement("button");
6182
+ confirm.type = "submit";
6183
+ confirm.className = "prompt-button";
6184
+ confirm.textContent = options.confirm;
6185
+ if (options.danger) {
6186
+ confirm.classList.add("danger");
6187
+ }
6188
+ actions.append(cancel, confirm);
6189
+ form.append(actions);
6190
+ dialog.append(header, form);
6191
+ form.onsubmit = (event) => {
6192
+ event.preventDefault();
6193
+ if (input && !input.value.trim()) {
6194
+ input.focus();
6195
+ return;
6196
+ }
6197
+ result = input?.value.trim() ?? "";
6198
+ dialog.close();
6199
+ };
6200
+ dialog.addEventListener("close", () => {
6201
+ dialog.remove();
6202
+ resolve2(result);
6203
+ }, { once: true });
6204
+ document.body.append(dialog);
6205
+ dialog.showModal();
6206
+ });
6207
+ }
6208
+
6130
6209
  // src/web/ui/host.ts
6131
6210
  function acquireWorkflowHost() {
6132
6211
  const embedded = globalThis.acquireVsCodeApi;
@@ -6229,7 +6308,7 @@ ${state2.user?.avatarUrl ?? ""}`;
6229
6308
  accountPanel = new AccountPanel(document.querySelector("#project-menu"), request);
6230
6309
  });
6231
6310
  return {
6232
- postMessage: (message) => {
6311
+ postMessage: async (message) => {
6233
6312
  if (message.type === "ready") {
6234
6313
  return;
6235
6314
  }
@@ -6242,13 +6321,13 @@ ${state2.user?.avatarUrl ?? ""}`;
6242
6321
  return;
6243
6322
  }
6244
6323
  if (message.type === "session-action" && message.action === "rename") {
6245
- const title = prompt("\u5BF9\u8BDD\u540D\u79F0");
6246
- if (!title) {
6324
+ const title = await requestAction({ title: "\u91CD\u547D\u540D\u5BF9\u8BDD", label: "\u5BF9\u8BDD\u540D\u79F0", value: message.currentTitle, confirm: "\u4FDD\u5B58" });
6325
+ if (title === void 0) {
6247
6326
  return;
6248
6327
  }
6249
6328
  message = { ...message, title };
6250
6329
  }
6251
- if (message.type === "session-action" && message.action === "delete" && !confirm("\u5220\u9664\u8FD9\u4E2A\u5BF9\u8BDD\uFF1F")) {
6330
+ if (message.type === "session-action" && message.action === "delete" && await requestAction({ title: "\u5220\u9664\u8FD9\u4E2A\u5BF9\u8BDD\uFF1F", confirm: "\u5220\u9664", danger: true }) === void 0) {
6252
6331
  return;
6253
6332
  }
6254
6333
  if (message.type === "open-file") {
@@ -6904,11 +6983,33 @@ ${state2.user?.avatarUrl ?? ""}`;
6904
6983
  try {
6905
6984
  const files = JSON.parse(String(value || "[]"));
6906
6985
  const list = Array.isArray(files) ? files : [files];
6907
- view.root.querySelector(".param-file-summary").textContent = list.map((file) => file?.name ?? "").join(", ");
6986
+ const summary = view.root.querySelector(".param-file-summary");
6987
+ if (this.options.downloadFile && summary.getAttribute("data-value") !== String(value)) {
6988
+ summary.setAttribute("data-value", String(value));
6989
+ summary.replaceChildren();
6990
+ for (const file of list.filter((file2) => file2 && typeof file2.id === "string")) {
6991
+ const row = document.createElement("span");
6992
+ row.className = "param-file-row";
6993
+ const name2 = document.createElement("span");
6994
+ name2.textContent = file.name;
6995
+ row.append(name2);
6996
+ const download = iconButton("cloud-download", "\u4E0B\u8F7D\u6587\u4EF6", () => this.options.downloadFile(file.id));
6997
+ const remove = iconButton("close", "\u79FB\u9664\u6587\u4EF6", () => this.options.change(field.name, JSON.stringify(list.filter((item) => item !== file))));
6998
+ download.classList.add("param-file-download");
6999
+ remove.classList.add("param-file-remove");
7000
+ row.append(download, remove);
7001
+ summary.append(row);
7002
+ }
7003
+ } else if (!this.options.downloadFile) {
7004
+ summary.textContent = list.map((file) => file?.name ?? "").join(", ");
7005
+ }
7006
+ for (const button of summary.querySelectorAll("button")) {
7007
+ button.disabled = this.options.disabled() || button.classList.contains("param-file-remove") && this.options.loading();
7008
+ }
6908
7009
  } catch {
6909
7010
  view.root.querySelector(".param-file-summary").textContent = "";
6910
7011
  }
6911
- view.root.querySelector("button").disabled = this.options.disabled() || this.options.loading() || !!state2?.disabled;
7012
+ view.root.querySelector(".param-file-button").disabled = this.options.disabled() || this.options.loading() || !!state2?.disabled;
6912
7013
  }
6913
7014
  }
6914
7015
  this.root.hidden = !Array.from(this.root.children).some((root) => !root.hidden);
@@ -7553,9 +7654,8 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
7553
7654
  summary.innerHTML = `${iconHtml(status === "running" ? "loading" : status === "failed" ? "error" : status === "success" ? "check" : "chevron-right")}<span>${escapeHtml(content?.tool ?? item.title ?? "\u8BE6\u60C5")}</span>`;
7554
7655
  root.append(summary);
7555
7656
  if (["audio", "video"].includes(item.contentType ?? "") && typeof content?.src === "string") {
7556
- const file = managedFileForUrl(content.src, files);
7557
- const src = file?.previewUrl ?? content.src;
7558
- if (/^https?:\/\//i.test(src) || new RegExp(`^data:${item.contentType}/[a-z0-9.+-]+;base64,`, "i").test(src)) {
7657
+ const src = mediaUrl(content.src, item.contentType === "audio" ? "audio" : "video", files, location.href);
7658
+ if (src) {
7559
7659
  const media = document.createElement(item.contentType === "audio" ? "audio" : "video");
7560
7660
  media.controls = true;
7561
7661
  media.preload = "metadata";
@@ -8184,7 +8284,7 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8184
8284
  var graphSignature = "";
8185
8285
  var editTimer;
8186
8286
  var searchTimer;
8187
- var prompt2;
8287
+ var prompt;
8188
8288
  var promptKey = "";
8189
8289
  var narrow = matchMedia("(max-width: 680px)");
8190
8290
  var dialogs = new ConversationTools();
@@ -8348,7 +8448,7 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8348
8448
  }
8349
8449
  element("usage").hidden = state?.account.status !== "authenticated";
8350
8450
  element("tools").disabled = !connected;
8351
- prompt2?.setBusy(!connected || state?.run?.status === "running" || submitting);
8451
+ prompt?.setBusy(!connected || state?.run?.status === "running" || submitting);
8352
8452
  app.dataset.connection = connected ? "connected" : "disconnected";
8353
8453
  }
8354
8454
  function historyRows(root) {
@@ -8474,7 +8574,7 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8474
8574
  renderedRun = run.id;
8475
8575
  tab = "result";
8476
8576
  graphSignature = "";
8477
- prompt2 = void 0;
8577
+ prompt = void 0;
8478
8578
  promptKey = "";
8479
8579
  element("run-prompt").replaceChildren();
8480
8580
  }
@@ -8516,9 +8616,9 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8516
8616
  if (key !== promptKey) {
8517
8617
  promptKey = key;
8518
8618
  element("run-prompt").replaceChildren();
8519
- prompt2 = void 0;
8619
+ prompt = void 0;
8520
8620
  if (run.pendingInput) {
8521
- prompt2 = new InputPrompt(run.pendingInput, {
8621
+ prompt = new InputPrompt(run.pendingInput, {
8522
8622
  submit: (values) => {
8523
8623
  submitting = true;
8524
8624
  controls();
@@ -8527,7 +8627,7 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8527
8627
  stop: () => post({ type: "workflow-stop" }),
8528
8628
  files: (name) => post({ type: "attach", runId: run.id, requestId: run.pendingInput.requestId, paramName: name, entrypointId: run.entrypointId })
8529
8629
  });
8530
- element("run-prompt").append(prompt2.root);
8630
+ element("run-prompt").append(prompt.root);
8531
8631
  }
8532
8632
  }
8533
8633
  element("logs-view").textContent = run.logs || "\u6682\u65E0\u65E5\u5FD7";
@@ -8614,9 +8714,10 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8614
8714
  post({ type: "workflow-rerun", id: state?.run?.id });
8615
8715
  };
8616
8716
  element("export-run").onclick = () => post({ type: "workflow-export", id: state?.run?.id });
8617
- element("delete-run").onclick = () => {
8618
- if (confirm("\u5220\u9664\u8FD9\u6761\u8FD0\u884C\u8BB0\u5F55\uFF1F")) {
8619
- post({ type: "workflow-delete", id: state?.run?.id });
8717
+ element("delete-run").onclick = async () => {
8718
+ const id = state?.run?.id;
8719
+ if (id && await requestAction({ title: "\u5220\u9664\u8FD9\u6761\u8FD0\u884C\u8BB0\u5F55\uFF1F", confirm: "\u5220\u9664", danger: true }) !== void 0) {
8720
+ post({ type: "workflow-delete", id });
8620
8721
  }
8621
8722
  };
8622
8723
  for (const name of ["result", "flow", "logs"]) {
@@ -8654,8 +8755,8 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8654
8755
  }
8655
8756
  controls();
8656
8757
  } else if (message?.type === "attachments") {
8657
- if (message.runId && prompt2 && message.requestId === prompt2.request.requestId) {
8658
- prompt2.fileValue(message.paramName, JSON.stringify(message.files));
8758
+ if (message.runId && prompt && message.requestId === prompt.request.requestId) {
8759
+ prompt.fileValue(message.paramName, JSON.stringify(message.files));
8659
8760
  } else if (message.entrypointId === entrypointId) {
8660
8761
  const field = parameters().fields.find((field2) => field2.name === message.paramName);
8661
8762
  if (field) {
@@ -8676,7 +8777,7 @@ ${JSON.stringify(output2.details, null, 2)}` : "");
8676
8777
  element("error").hidden = false;
8677
8778
  }
8678
8779
  if (message.requestType === "workflow-resume") {
8679
- prompt2?.setBusy(false, message.message);
8780
+ prompt?.setBusy(false, message.message);
8680
8781
  }
8681
8782
  if (message.requestType === "usage") {
8682
8783
  dialogs.usageResult(void 0, message.message);