@qilin-agent/client-ui-conversation 3.1.6 → 3.1.7

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.
package/lib/client.js CHANGED
@@ -8044,6 +8044,48 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8044
8044
  }
8045
8045
  }
8046
8046
  //#endregion
8047
+ //#region ../../context/file-reference/src/grammar.ts
8048
+ /**
8049
+ * Format a selected path as prompt text. Whitespace uses the quoted
8050
+ * `@"path"` grammar; a quoted directory keeps that quote open after its
8051
+ * trailing slash so completion can descend another level.
8052
+ * @param candidate - selected file or directory.
8053
+ * @param preserveQuote - retain an explicitly opened quote even when unnecessary.
8054
+ * @returns the insertion value, or `undefined` for a path the editor grammar cannot represent safely.
8055
+ */
8056
+ function formatFileMention(candidate, preserveQuote) {
8057
+ const path = candidate.kind === "directory" ? `${candidate.path}/` : candidate.path;
8058
+ if (/[\u0000-\u001f\u007f-\u009f"]/u.test(path)) return void 0;
8059
+ if (!(preserveQuote || /\s/u.test(path))) return `@${path}`;
8060
+ if (candidate.kind === "directory") return `@"${path}`;
8061
+ return `@"${path}"`;
8062
+ }
8063
+ //#endregion
8064
+ //#region ../../util/workspace-path/src/index.ts
8065
+ /**
8066
+ * Read the final non-empty segment of a Workspace path for display.
8067
+ * Workspace-label surfaces use this helper instead of deriving another basename.
8068
+ * @param path - Workspace directory path using POSIX or Windows separators.
8069
+ * @returns the final segment, or an empty string for a separator-only path.
8070
+ */
8071
+ function workspaceTitleOf(path) {
8072
+ const trimmed = path.replace(/[/\\]+$/, "");
8073
+ const separator = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
8074
+ return trimmed.slice(separator + 1);
8075
+ }
8076
+ /**
8077
+ * Strip the workspace root from a workspace-rooted absolute path (display only).
8078
+ * @param text - the path to shorten.
8079
+ * @param cwd - session workspace root; absent or empty leaves the path unchanged.
8080
+ * @returns the path relative to the workspace root, or unchanged when it is not rooted there.
8081
+ */
8082
+ function relativizeToCwd(text, cwd) {
8083
+ if (cwd === void 0 || cwd === "") return text;
8084
+ const root = cwd.replace(/[/\\]+$/, "");
8085
+ if (text.startsWith(`${root}/`) || text.startsWith(`${root}\\`)) return text.slice(root.length + 1);
8086
+ return text;
8087
+ }
8088
+ //#endregion
8047
8089
  //#region lib/types/client/service.js
8048
8090
  /**
8049
8091
  * Scope-addressed conversation send, cancel, and history orchestration.
@@ -11006,7 +11048,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11006
11048
  function po(t) {
11007
11049
  return t instanceof _o;
11008
11050
  }
11009
- const mo = "history-push", xo = "history-merge", Co = "paste", ko = "skip-scroll-into-view", No = "skip-selection-focus", wo = "composition-end", Oo = "!important";
11051
+ const mo = "history-push", xo = "history-merge", Co = "paste", ko = "skip-scroll-into-view", bo = "skip-dom-selection", No = "skip-selection-focus", wo = "composition-end", Oo = "!important";
11010
11052
  function Mo(t) {
11011
11053
  const e = {};
11012
11054
  if (!t) return e;
@@ -17147,7 +17189,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17147
17189
  className: ReferenceChip_module_css_default.marker,
17148
17190
  "aria-hidden": true,
17149
17191
  children: "@"
17150
- }) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.ReferenceIcon, {
17192
+ }) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.ReferenceIconRegular, {
17151
17193
  kind: appearance,
17152
17194
  size: 14,
17153
17195
  className: ReferenceChip_module_css_default.icon
@@ -18061,6 +18103,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18061
18103
  * literal one in text would forge chip positions.
18062
18104
  */
18063
18105
  const REFERENCE_PLACEHOLDER_RE = /[\uE100-\uE11D\uFFFC]/gu;
18106
+ /**
18107
+ * Append one paragraph per line of `text` to the editor root and move the caret
18108
+ * to the end. Must run inside an editor update.
18109
+ * @param text - sanitized plain text.
18110
+ */
18111
+ function $appendParagraphs(text) {
18112
+ const root = nl();
18113
+ for (const line of text.split("\n")) {
18114
+ const paragraph = es();
18115
+ if (line !== "") paragraph.append(Go(line));
18116
+ root.append(paragraph);
18117
+ }
18118
+ root.selectEnd();
18119
+ }
18064
18120
  /** Undo merge window for contiguous typing, in ms (the old machine's mergeWindowMs). */
18065
18121
  const HISTORY_MERGE_DELAY_MS = 1e3;
18066
18122
  /** One model-owned editor; registration and disposal remain with its model. */
@@ -18102,7 +18158,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18102
18158
  * @returns unregister callback that also detaches the editor root.
18103
18159
  */
18104
18160
  register() {
18105
- const unregister = Eu(O$1(this.editor), registerReferenceActivation(this.editor, (source, reference) => this.deps.openReference(source, reference)), O(this.editor, z(), HISTORY_MERGE_DELAY_MS), this.editor.registerUpdateListener(() => {
18161
+ const preserveExternalSelection = () => {
18162
+ const root = this.editor.getRootElement();
18163
+ if (root !== null && !root.contains(root.ownerDocument.activeElement)) Al(bo);
18164
+ return false;
18165
+ };
18166
+ const unregister = Eu(O$1(this.editor), this.editor.registerCommand(Mn$1, () => {
18167
+ this.editor.update(preserveExternalSelection, { discrete: true });
18168
+ return false;
18169
+ }, 4), this.editor.registerCommand(Ie$2, preserveExternalSelection, 4), this.editor.registerNodeTransform(zi, preserveExternalSelection), registerReferenceActivation(this.editor, (source, reference) => this.deps.openReference(source, reference)), O(this.editor, z(), HISTORY_MERGE_DELAY_MS), this.editor.registerUpdateListener(() => {
18106
18170
  this.deps.onUpdate();
18107
18171
  }), registerCommandChipSeat(this.editor), registerCommandChipSelection(this.editor), registerTextRefDecoration(this.editor, () => this.deps.lexicon()), () => {
18108
18172
  this.lexiconOff?.();
@@ -18178,14 +18242,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18178
18242
  const clean = text.replace(REFERENCE_PLACEHOLDER_RE, "");
18179
18243
  if (clean === this.projection.clipboardText && this.projection.occurrences.length === 0) return;
18180
18244
  this.editor.update(() => {
18181
- const root = nl();
18182
- root.clear();
18183
- for (const line of clean.split("\n")) {
18184
- const paragraph = es();
18185
- if (line !== "") paragraph.append(Go(line));
18186
- root.append(paragraph);
18187
- }
18188
- root.selectEnd();
18245
+ nl().clear();
18246
+ $appendParagraphs(clean);
18247
+ }, {
18248
+ discrete: true,
18249
+ tag: xo
18250
+ });
18251
+ }
18252
+ /**
18253
+ * Add plain text after the current draft as new paragraphs, keeping its text
18254
+ * and references; an empty draft takes the text as its whole content.
18255
+ * Placeholder-sanitized; the caret lands at the end; merged into history
18256
+ * like {@link setDraft}.
18257
+ * @param text - plain text to add.
18258
+ */
18259
+ appendDraft(text) {
18260
+ const clean = text.replace(REFERENCE_PLACEHOLDER_RE, "");
18261
+ if (clean === "") return;
18262
+ if (this.projection.clipboardText === "" && this.projection.occurrences.length === 0) {
18263
+ this.setDraft(clean);
18264
+ return;
18265
+ }
18266
+ this.editor.update(() => {
18267
+ $appendParagraphs(clean);
18189
18268
  }, {
18190
18269
  discrete: true,
18191
18270
  tag: xo
@@ -18286,6 +18365,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18286
18365
  return applied;
18287
18366
  }
18288
18367
  /**
18368
+ * Insert an ordered file-reference batch after the live selection without deleting it.
18369
+ * @param references - validated references in source order.
18370
+ * @returns whether the live insertion position accepted the batch.
18371
+ */
18372
+ insertFileReferences(references) {
18373
+ if (references.length === 0) return true;
18374
+ let applied = false;
18375
+ this.applyEdit(() => {
18376
+ const projection = $projectComposer((key) => this.occurrenceIdOf(key));
18377
+ const at = projection.selection?.end ?? projection.detectText.length;
18378
+ const before = projection.detectText.slice(0, at);
18379
+ const nodes = references.flatMap((ref) => [$createReferenceChipNode(ref), Go(" ")]);
18380
+ if (before !== "" && !/\s$/u.test(before)) nodes.unshift(Go(" "));
18381
+ applied = $replaceDetectSpanWithNodes({
18382
+ start: at,
18383
+ end: at
18384
+ }, nodes);
18385
+ }, Co);
18386
+ return applied;
18387
+ }
18388
+ /**
18289
18389
  * Clear committed content using the model's suffix decision inside the editor update.
18290
18390
  * @param prefixLength - returns the clipboard-prefix length to remove, or null to clear the root.
18291
18391
  */
@@ -18558,14 +18658,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18558
18658
  }
18559
18659
  /**
18560
18660
  * Apply one new-task request to this already-initialized input model.
18561
- * @param options - replacement content and explicit permission to clear existing text.
18562
- * @returns whether text changed, was preserved, or submission prevented editing.
18661
+ * @param options - content to adopt and the handling of an existing draft.
18662
+ * @returns applied when the requested text is adopted, even if unchanged;
18663
+ * preserved when the current draft is kept; blocked after disposal or during a pending submission.
18563
18664
  */
18564
18665
  requestDraftInitialization(options) {
18565
18666
  if (this.draftInitializationBlocked()) return "blocked";
18566
- if (options.prompt === void 0 && options.clearPreviousDraft !== true) return "preserved";
18567
- if (options.clearPreviousDraft !== true && (this.snapshot.draft !== "" || this.attachmentIds.length > 0)) return "preserved";
18568
- this.setDraft(options.prompt ?? "");
18667
+ const whenDraftExists = options.whenDraftExists ?? (options.clearPreviousDraft === true ? "replace" : "keep");
18668
+ if (whenDraftExists === "replace") {
18669
+ this.setDraft(options.prompt ?? "");
18670
+ return "applied";
18671
+ }
18672
+ if (options.prompt === void 0) return "preserved";
18673
+ if (this.snapshot.draft === "" && this.attachmentIds.length === 0) {
18674
+ this.setDraft(options.prompt);
18675
+ return "applied";
18676
+ }
18677
+ if (whenDraftExists === "keep") return "preserved";
18678
+ this.draftEditor.appendDraft(options.prompt);
18569
18679
  return "applied";
18570
18680
  }
18571
18681
  draftInitializationBlocked() {
@@ -18581,6 +18691,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18581
18691
  return true;
18582
18692
  }
18583
18693
  /**
18694
+ * Add validated file references and attachment ids while admission is editable.
18695
+ * @param references - reference chips in source order.
18696
+ * @param ids - newly allocated attachment ids.
18697
+ * @returns false when admission is locked or the editor refuses the insertion.
18698
+ */
18699
+ addFiles(references, ids) {
18700
+ if (this.snapshot.phase === "adjudicating" || this.snapshot.phase === "submitting") return false;
18701
+ if (!this.draftEditor.insertFileReferences(references)) return false;
18702
+ this.attachmentIds = [...this.attachmentIds, ...ids];
18703
+ this.publish();
18704
+ return true;
18705
+ }
18706
+ /**
18584
18707
  * Remove one attachment id from this draft. Busy admission phases refuse, like
18585
18708
  * {@link addAttachments}: a removal landing while a command submit serializes
18586
18709
  * would otherwise vanish from the rail yet still ride the in-flight send.
@@ -18643,6 +18766,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18643
18766
  attachmentIds
18644
18767
  });
18645
18768
  this.commitSend(attachmentIds);
18769
+ this.notifySubmission(this.submissionFor(mode));
18646
18770
  this.deps.defaultSink("", attachmentIds, mode, controller.signal).then((outcome) => {
18647
18771
  if (this.disposed || !this.attachmentFlights.delete(flight)) return;
18648
18772
  if (outcome.kind === "success") return;
@@ -18942,6 +19066,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18942
19066
  * its editor snapshot. Chip-free drafts skip the async detour.
18943
19067
  */
18944
19068
  sinkSerialized(attempt, draft, mode) {
19069
+ this.notifySubmission(this.submissionFor(mode));
18945
19070
  const attachmentIds = [...this.attachmentIds];
18946
19071
  this.attachmentIds = [];
18947
19072
  const occurrences = this.projection.occurrences;
@@ -18983,6 +19108,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18983
19108
  this.settleDetachedFailure(attempt, message);
18984
19109
  });
18985
19110
  }
19111
+ /**
19112
+ * Capture the notification's Session facts; an observation failure leaves them unknown.
19113
+ * @param mode - delivery mode requested for this attempt.
19114
+ * @returns the immutable occurrence.
19115
+ */
19116
+ submissionFor(mode) {
19117
+ let state;
19118
+ try {
19119
+ state = this.deps.submissionState?.();
19120
+ } catch (_error) {}
19121
+ return Object.freeze({
19122
+ timestamp: Date.now(),
19123
+ mode,
19124
+ ...state === void 0 ? {} : { state }
19125
+ });
19126
+ }
19127
+ /**
19128
+ * Hand one occurrence to the notification consumer; a consumer failure cannot interrupt sending.
19129
+ * @param submission - captured occurrence.
19130
+ */
19131
+ notifySubmission(submission) {
19132
+ try {
19133
+ this.deps.messageSubmitted?.(submission);
19134
+ } catch (_error) {}
19135
+ }
18986
19136
  /** Settle one detached default send independently of other sends. */
18987
19137
  settleSink(attempt, pending) {
18988
19138
  pending.then((outcome) => {
@@ -19147,6 +19297,44 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19147
19297
  }
19148
19298
  };
19149
19299
  //#endregion
19300
+ //#region lib/types/client/input/submission-analytics.js
19301
+ /**
19302
+ * Map a preset id to its fixed analytics category; custom ids never leave the Client.
19303
+ * @param id - Agent preset id the Session records.
19304
+ * @returns the built-in category, or other.
19305
+ */
19306
+ function analyticsPreset(id) {
19307
+ switch (id) {
19308
+ case "cordis": return "creator";
19309
+ case "ptc": return "ptc";
19310
+ case "minimal": return "minimal";
19311
+ case "standard": return "standard";
19312
+ default: return "other";
19313
+ }
19314
+ }
19315
+ /**
19316
+ * Report the original message occurrence without reading newer Session facts.
19317
+ * @param ctx - client context.
19318
+ * @param submission - occurrence, delivery mode, and captured Session facts.
19319
+ */
19320
+ function reportMessageSubmission(ctx, submission) {
19321
+ const { state, timestamp } = submission;
19322
+ if (state === void 0) return;
19323
+ const { mode } = submission;
19324
+ const { model } = state;
19325
+ ctx.get("productAnalytics")?.track("send_button_click", {
19326
+ ...state.sessionId === void 0 ? {} : { session_id: state.sessionId },
19327
+ ...model === void 0 ? {} : {
19328
+ model_name: `${model.provider}/${model.name}`,
19329
+ ...model.effort === void 0 ? {} : { thinking_effort: model.effort }
19330
+ },
19331
+ run_mode: state.runMode,
19332
+ msg_type: state.running ? mode : "default",
19333
+ is_new_session: state.newSession,
19334
+ ...state.agentPreset === void 0 ? {} : { agent_preset: analyticsPreset(state.agentPreset) }
19335
+ }, timestamp);
19336
+ }
19337
+ //#endregion
19150
19338
  //#region lib/types/client/input/hub.js
19151
19339
  /** Session-addressed input facade registry (SessionInputResolver face + composer-layer extras). */
19152
19340
  var InputHub = class {
@@ -19191,6 +19379,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19191
19379
  const { session, ctx: actx } = binding;
19192
19380
  const shell = new SessionInputShell({
19193
19381
  actx,
19382
+ submissionState: () => {
19383
+ const state = session.getSnapshot();
19384
+ const model = session.projections.faceOf("modelSelection").getSnapshot();
19385
+ const plan = session.projections.faceOf("plan").getSnapshot();
19386
+ const goal = session.projections.faceOf("goal").getSnapshot();
19387
+ const agentPreset = session.projections.faceOf("agentPreset").getSnapshot();
19388
+ const selection = model?.next ?? model?.lastUsed;
19389
+ return Object.freeze({
19390
+ ...state.blank ? {} : { sessionId: state.sessionId },
19391
+ ...selection == null ? {} : { model: Object.freeze({
19392
+ provider: selection.provider,
19393
+ name: selection.model,
19394
+ ...selection.reasoningEffort === void 0 ? {} : { effort: selection.reasoningEffort }
19395
+ }) },
19396
+ runMode: plan?.active ? "plan" : goal?.goal.phase === "active" ? "goal" : "default",
19397
+ running: state.running,
19398
+ newSession: state.blank,
19399
+ ...typeof agentPreset === "string" ? { agentPreset } : {}
19400
+ });
19401
+ },
19402
+ messageSubmitted: (submission) => {
19403
+ reportMessageSubmission(this.rootCtx, submission);
19404
+ },
19194
19405
  inputTriggers: () => this.controller(actx),
19195
19406
  popup: () => this.popup(actx),
19196
19407
  inbox: session.projections.faceOf("inbox"),
@@ -19559,6 +19770,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19559
19770
  "attachment.dropTitle": "文件或图片拖动到此处即可添加",
19560
19771
  "attachment.dropDesc": "图片限制:最多 {count} 张,每张 {size}",
19561
19772
  "attachment.dropBlocked": "当前无法添加文件或图片",
19773
+ "attachment.directoryDesktopOnly": "只有桌面端支持添加文件夹,浏览器里请添加单个文件",
19774
+ "attachment.pathUnavailable": "无法获取文件夹路径,请重新拖入",
19775
+ "attachment.pathUnsupported": "路径含有无法引用的字符,请改名后再试",
19562
19776
  "image.pending": "待发送图片",
19563
19777
  "image.openOriginal": "查看原图",
19564
19778
  "image.openOriginalLabel": "{label},点击查看原图",
@@ -19602,6 +19816,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19602
19816
  "hero.greeting.evening": "晚上好,今天辛苦了",
19603
19817
  "hero.chooseWorkspace": "选择工作区",
19604
19818
  "session.hierarchy": "会话层级",
19819
+ "session.moreViews": "更多会话视图",
19820
+ "session.moreViewsCurrent": "更多会话视图 · {name}",
19605
19821
  "todo.title": "任务",
19606
19822
  "todo.progress.done": "{done} 已完成",
19607
19823
  "todo.progress.active": "{active} 进行中",
@@ -19935,6 +20151,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19935
20151
  "attachment.dropTitle": "Drag files or images here to add them",
19936
20152
  "attachment.dropDesc": "Image limit: up to {count} images, {size} each",
19937
20153
  "attachment.dropBlocked": "Files and images cannot be added right now",
20154
+ "attachment.directoryDesktopOnly": "Folders can only be added in the desktop app; add individual files in the browser",
20155
+ "attachment.pathUnavailable": "Could not obtain the folder path; drag it in again",
20156
+ "attachment.pathUnsupported": "The path contains characters a reference cannot carry; rename it and try again",
19938
20157
  "image.pending": "Pending images",
19939
20158
  "image.openOriginal": "View original",
19940
20159
  "image.openOriginalLabel": "{label}, click to view original",
@@ -19978,6 +20197,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19978
20197
  "hero.greeting.evening": "Good evening, great job today",
19979
20198
  "hero.chooseWorkspace": "Choose workspace",
19980
20199
  "session.hierarchy": "Session hierarchy",
20200
+ "session.moreViews": "More conversation views",
20201
+ "session.moreViewsCurrent": "More conversation views · {name}",
19981
20202
  "todo.title": "To-dos",
19982
20203
  "todo.progress.done": "{done} completed",
19983
20204
  "todo.progress.active": "{active} in progress",
@@ -20475,7 +20696,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20475
20696
  (0, react_jsx_runtime.jsx)("span", {
20476
20697
  className: QueueDock_module_css_default.lead,
20477
20698
  "aria-hidden": true,
20478
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutline14, {})
20699
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutlineRegular, {})
20479
20700
  }),
20480
20701
  (0, react_jsx_runtime.jsx)("span", {
20481
20702
  className: QueueDock_module_css_default.count,
@@ -20489,7 +20710,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20489
20710
  (0, react_jsx_runtime.jsx)("span", {
20490
20711
  className: QueueDock_module_css_default.chevron,
20491
20712
  "aria-hidden": true,
20492
- children: expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronUpOutline14, {})
20713
+ children: expanded ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronUpOutlineRegular, {})
20493
20714
  })
20494
20715
  ]
20495
20716
  }), (0, react_jsx_runtime.jsxs)("ul", {
@@ -20505,7 +20726,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20505
20726
  rowCount === 1 && (0, react_jsx_runtime.jsx)("span", {
20506
20727
  className: QueueDock_module_css_default.lead,
20507
20728
  "aria-hidden": true,
20508
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutline14, {})
20729
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutlineRegular, {})
20509
20730
  }),
20510
20731
  editing?.id === row.id ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.InlineEditor, {
20511
20732
  value: editing.text,
@@ -20550,7 +20771,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20550
20771
  onClick: () => {
20551
20772
  saveEdit();
20552
20773
  },
20553
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCheckOutline16, { size: 14 })
20774
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCheckOutlineRegular, { size: 14 })
20554
20775
  })
20555
20776
  }), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
20556
20777
  label: t("queue.cancelEdit"),
@@ -20564,7 +20785,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20564
20785
  onClick: () => {
20565
20786
  setEditing(null);
20566
20787
  },
20567
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCloseOutline16, { size: 14 })
20788
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconCloseOutlineRegular, { size: 14 })
20568
20789
  })
20569
20790
  })] }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
20570
20791
  (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
@@ -20584,7 +20805,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20584
20805
  text
20585
20806
  });
20586
20807
  },
20587
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconEditOutline16, { size: 14 })
20808
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconEditOutlineRegular, { size: 14 })
20588
20809
  })
20589
20810
  }),
20590
20811
  (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
@@ -20599,7 +20820,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20599
20820
  onClick: () => {
20600
20821
  applyAction(row.id, { kind: "remove" }, t("queue.removeFailed"));
20601
20822
  },
20602
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutline16, { size: 14 })
20823
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
20603
20824
  })
20604
20825
  }),
20605
20826
  (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
@@ -20616,7 +20837,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20616
20837
  onClick: () => {
20617
20838
  applyAction(row.id, { kind: "steer" }, t("queue.steerFailed"));
20618
20839
  },
20619
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconSendOutline14, {})
20840
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconSendOutlineRegular, {})
20620
20841
  })
20621
20842
  })
20622
20843
  ] })
@@ -20631,7 +20852,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20631
20852
  rowCount === 1 && (0, react_jsx_runtime.jsx)("span", {
20632
20853
  className: QueueDock_module_css_default.lead,
20633
20854
  "aria-hidden": true,
20634
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutline14, {})
20855
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconQueueOutlineRegular, {})
20635
20856
  }),
20636
20857
  submission.attachments.length > 0 && (0, react_jsx_runtime.jsx)("span", {
20637
20858
  className: QueueDock_module_css_default.attachments,
@@ -20662,7 +20883,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20662
20883
  "aria-label": t("queue.edit"),
20663
20884
  title: t("queue.sending"),
20664
20885
  disabled: true,
20665
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconEditOutline16, { size: 14 })
20886
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconEditOutlineRegular, { size: 14 })
20666
20887
  }),
20667
20888
  (0, react_jsx_runtime.jsx)("button", {
20668
20889
  type: "button",
@@ -20670,7 +20891,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20670
20891
  "aria-label": t("queue.remove"),
20671
20892
  title: t("queue.sending"),
20672
20893
  disabled: true,
20673
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutline16, { size: 14 })
20894
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconTrashOutlineRegular, { size: 14 })
20674
20895
  }),
20675
20896
  (0, react_jsx_runtime.jsx)("button", {
20676
20897
  type: "button",
@@ -20678,7 +20899,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20678
20899
  "aria-label": t("queue.steer"),
20679
20900
  title: t("queue.sending"),
20680
20901
  disabled: true,
20681
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconSendOutline14, {})
20902
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconSendOutlineRegular, {})
20682
20903
  })
20683
20904
  ]
20684
20905
  })
@@ -20793,7 +21014,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20793
21014
  onClick: () => {
20794
21015
  setOpen((value) => !value);
20795
21016
  },
20796
- children: [t(selectedLabel), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, { className: EnterBehaviorRow_module_css_default.chevron })]
21017
+ children: [t(selectedLabel), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, { className: EnterBehaviorRow_module_css_default.chevron })]
20797
21018
  })
20798
21019
  })]
20799
21020
  });
@@ -20945,7 +21166,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20945
21166
  }
20946
21167
  //#endregion
20947
21168
  //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css.mjs
20948
- const css$4 = ".tABNoa_root{background:var(--qilin-alias-bg-base);flex-direction:column;min-width:0;height:100%;display:flex;position:relative}.tABNoa_header{box-sizing:border-box;border-bottom:.5px solid var(--qilin-alias-border-l3);flex:none;align-items:center;height:48px;padding:0 28px 0 20px;display:flex}.tABNoa_header:has(.tABNoa_tabs){height:76px;padding:10px 28px 0 20px;display:block}.tABNoa_headerBlank{border-bottom:none;min-height:0}.tABNoa_headerBlank .tABNoa_headerCorner{margin-left:auto}.tABNoa_headerSessionless{min-height:0;padding-bottom:10px}.tABNoa_headerSessionless .tABNoa_titleRow{min-height:0}html:not([data-platform=darwin]) .tABNoa_headerSessionless{padding-top:0}[data-platform=darwin] .tABNoa_headerLeading,[data-platform=darwin] .tABNoa_headerActions,[data-platform=darwin] .tABNoa_headerUtilities,[data-platform=darwin] .tABNoa_headerCorner{-webkit-app-region:no-drag}.tABNoa_titleRow{flex:1;align-items:center;gap:0;min-height:30px;display:flex}.tABNoa_titleCluster{flex:1;align-items:center;gap:10px;min-width:0;display:flex}.tABNoa_headerLeading{flex:none;align-items:center;gap:8px;display:flex}.tABNoa_headerLeading:empty{display:none}.tABNoa_crumbs{white-space:nowrap;align-items:center;gap:4px;min-width:0;display:flex;overflow:hidden}.tABNoa_crumbSeg{align-items:center;gap:4px;min-width:0;display:inline-flex}.tABNoa_crumbSep{color:var(--qilin-alias-label-caption);font-size:14px;line-height:20px}.tABNoa_crumb{max-width:220px;color:var(--qilin-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:12px;padding:4px 8px;font-size:14px;line-height:20px;overflow:hidden}.tABNoa_crumbSubagent{font-size:12px;line-height:18px}.tABNoa_crumb:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.tABNoa_crumbCurrent{color:var(--qilin-alias-label-primary);cursor:default;font-weight:500}.tABNoa_headerActions{flex:none;align-items:center;gap:8px;display:flex}.tABNoa_headerUtilities{flex:none;align-items:center;gap:8px;margin-left:20px;display:flex}.tABNoa_headerUtilities:empty{display:none}.tABNoa_headerCorner{flex:none;align-items:center;margin-left:8px;margin-right:-16px;display:flex}.tABNoa_headerCorner:empty{display:none}.tABNoa_tabs{z-index:1;gap:36px;margin-top:10px;padding-left:8px;display:flex;position:relative}.tABNoa_tab{color:var(--qilin-alias-label-tertiary);cursor:pointer;background:0 0;border:none;padding:0 0 9px;font-size:13px;font-weight:500;line-height:16px;position:relative}.tABNoa_tab:after{content:\"\";background:0 0;border-radius:2px;height:2px;position:absolute;bottom:-1px;left:0;right:0}.tABNoa_tabActive{color:var(--qilin-alias-state-business-primary)}.tABNoa_tabActive:after{background:var(--qilin-alias-state-business-primary)}.tABNoa_viewArea{flex-direction:column;flex:1;min-height:0;display:flex}.tABNoa_widthHandle{z-index:0;width:min(10px, calc((100% - var(--qilin-chat-content-width)) / 2 - 24px - 24px));cursor:col-resize;position:absolute;top:0;bottom:0}.tABNoa_widthHandle[data-side=left]{right:calc(50% + var(--qilin-chat-content-width) / 2 + 24px)}.tABNoa_widthHandle[data-side=right]{left:calc(50% + var(--qilin-chat-content-width) / 2 + 24px)}.tABNoa_widthHandle:after{content:\"\";background:linear-gradient(to bottom, transparent calc(var(--qilin-width-handle-pointer-y,50%) - 36px), var(--qilin-alias-scrollbar-bg-l1) calc(var(--qilin-width-handle-pointer-y,50%) - 8px), var(--qilin-alias-scrollbar-bg-l1) calc(var(--qilin-width-handle-pointer-y,50%) + 8px), transparent calc(var(--qilin-width-handle-pointer-y,50%) + 36px));opacity:0;pointer-events:none;border-radius:2px;width:2px;position:absolute;top:0;bottom:0}.tABNoa_widthHandle[data-side=left]:after{right:4px}.tABNoa_widthHandle[data-side=right]:after{left:4px}.tABNoa_widthHandle:hover:after,.tABNoa_widthHandle[data-dragging]:after{opacity:1}.tABNoa_widthHandle[data-dragging]{z-index:8}.tABNoa_composerStack{--qilin-composer-stack-gap:6px;gap:var(--qilin-composer-stack-gap);flex-direction:column;display:flex}.tABNoa_composerSeat{--qilin-composer-text-max-height:336px;flex-direction:column;flex:none;display:flex}.tABNoa_root[data-phase=active]{overflow:hidden}.tABNoa_root[data-phase=active] .tABNoa_header{flex:none}.tABNoa_body{--qilin-chat-content-width:var(--qilin-chat-user-width,clamp(680px, calc(var(--qilin-conversation-column-width,0px) * .64), 920px));--qilin-composer-card-max-width:calc(var(--qilin-chat-content-width) + 32px);--qilin-composer-side-clearance:16px;--qilin-composer-dock-inset:8px;flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.tABNoa_embeddedBody{--qilin-chat-content-width:min(calc(100% - 32px), 920px);--qilin-composer-card-max-width:min(calc(100% - 16px), 952px);--qilin-composer-side-clearance:8px;--qilin-composer-dock-inset:8px;overflow:hidden}.tABNoa_scrollBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;margin-right:2px;display:flex;overflow-y:auto}.tABNoa_scrollBody::-webkit-scrollbar-track{margin:2px}.tABNoa_root[data-phase=active] .tABNoa_viewArea,.tABNoa_embeddedBody[data-content-phase=active] .tABNoa_viewArea{flex:1 0 auto;min-height:auto}.tABNoa_root[data-phase=active] .tABNoa_composerSeat,.tABNoa_embeddedBody[data-content-phase=active] .tABNoa_composerSeat{z-index:7;background:linear-gradient(180deg, color-mix(in srgb, var(--qilin-alias-bg-base) 0%, transparent) 0px, var(--qilin-alias-bg-base) 36px);position:sticky;bottom:0}.tABNoa_root[data-phase=active] .tABNoa_composerSeat:has([data-trigger-menu]){z-index:9}.tABNoa_composerHero{width:min(calc(var(--qilin-composer-card-max-width) + 2 * var(--qilin-composer-side-clearance)), 100%);z-index:1;align-self:center;gap:8px;padding-bottom:32px}.tABNoa_heroWorkspaceRow{align-items:center;gap:2px;min-width:0;margin-top:4px;padding:0 16px 0 20px;display:flex}.tABNoa_heroOptions{flex:none;align-items:center;gap:2px;min-width:0;margin-left:auto;display:flex}.tABNoa_heroOptions:empty{display:none}.tABNoa_root[data-phase=hero] .tABNoa_scrollBody,.tABNoa_embeddedBody[data-content-phase=hero] .tABNoa_scrollBody{justify-content:center;overflow-y:auto}.tABNoa_root[data-phase=settling] .tABNoa_composerSeat,.tABNoa_embeddedBody[data-content-phase=settling] .tABNoa_composerSeat{visibility:hidden}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_header:has(.tABNoa_tabs){grid-template-rows:30px auto;grid-template-columns:auto minmax(0,1fr);align-items:start;column-gap:0;display:grid}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_header:has(.tABNoa_tabs)>div:not(.tABNoa_headerLeading):has(.tABNoa_titleRow){display:contents}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_headerLeading{grid-area:1/1}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_titleRow{grid-area:1/2}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_tabs{grid-area:2/1/auto/-1}";
21169
+ const css$4 = ".tABNoa_root{background:var(--qilin-alias-bg-base);flex-direction:column;min-width:0;height:100%;display:flex;position:relative}.tABNoa_header{box-sizing:border-box;border-bottom:.5px solid var(--qilin-alias-border-l3);flex:none;align-items:center;height:48px;padding:0 28px 0 20px;display:flex}.tABNoa_header:has(.tABNoa_tabs){height:76px;padding:10px 28px 0 20px;display:block}.tABNoa_headerBlank{border-bottom:none;min-height:0}.tABNoa_headerBlank .tABNoa_headerCorner{margin-left:auto}.tABNoa_headerSessionless{min-height:0;padding-bottom:10px}.tABNoa_headerSessionless .tABNoa_titleRow{min-height:0}html:not([data-platform=darwin]) .tABNoa_headerSessionless{padding-top:0}[data-platform=darwin] .tABNoa_headerLeading,[data-platform=darwin] .tABNoa_headerActions,[data-platform=darwin] .tABNoa_headerUtilities,[data-platform=darwin] .tABNoa_headerCorner{-webkit-app-region:no-drag}.tABNoa_titleRow{flex:1;align-items:center;gap:0;min-height:30px;display:flex}.tABNoa_titleCluster{flex:1;align-items:center;gap:10px;min-width:0;display:flex}.tABNoa_headerLeading{flex:none;align-items:center;gap:8px;display:flex}.tABNoa_headerLeading:empty{display:none}.tABNoa_crumbs{white-space:nowrap;align-items:center;gap:4px;min-width:0;display:flex;overflow:hidden}.tABNoa_crumbSeg{align-items:center;gap:4px;min-width:0;display:inline-flex}.tABNoa_crumbSep{color:var(--qilin-alias-label-caption);font-size:14px;line-height:20px}.tABNoa_crumb{max-width:220px;color:var(--qilin-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-radius:12px;padding:4px 8px;font-size:14px;line-height:20px;overflow:hidden}.tABNoa_crumbSubagent{font-size:12px;line-height:18px}.tABNoa_crumb:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover)}.tABNoa_crumbCurrent{color:var(--qilin-alias-label-primary);cursor:default;font-weight:500}.tABNoa_headerActions{flex:none;align-items:center;gap:8px;display:flex}.tABNoa_headerUtilities{flex:none;align-items:center;gap:8px;margin-left:20px;display:flex}.tABNoa_headerUtilities:empty{display:none}.tABNoa_headerCorner{flex:none;align-items:center;margin-left:8px;margin-right:-16px;display:flex}.tABNoa_headerCorner:empty{display:none}.tABNoa_tabs{z-index:1;box-sizing:border-box;flex-wrap:wrap;grid-column:1/-1;align-items:flex-start;gap:16px 20px;width:100%;min-width:0;margin-top:10px;padding-left:8px;display:flex;position:relative}.tABNoa_viewTabs{flex-wrap:wrap;gap:32px;min-width:0;min-height:25px;display:flex}.tABNoa_tab{min-height:25px;color:var(--qilin-alias-label-tertiary);cursor:pointer;background:0 0;border:none;padding:0 0 9px;font-size:13px;font-weight:500;line-height:16px;position:relative}.tABNoa_tab:after{content:\"\";background:0 0;border-radius:2px;height:2px;position:absolute;bottom:-1px;left:0;right:0}.tABNoa_tabActive{color:var(--qilin-alias-state-business-primary)}.tABNoa_tabActive:after{background:var(--qilin-alias-state-business-primary)}.tABNoa_viewsMoreAnchor{flex:none}.tABNoa_viewsMore{width:22px;height:22px;color:var(--qilin-alias-label-secondary);margin-top:-3px;padding:0}.tABNoa_viewsMoreActive{color:var(--qilin-alias-state-business-primary)}.tABNoa_tabLabel{text-overflow:ellipsis;white-space:nowrap;max-width:88px;display:block;overflow:hidden}.tABNoa_viewsMore[aria-expanded=true]{background:var(--qilin-alias-interactive-bg-hover)}.tABNoa_viewsMoreMenu{width:288px;max-width:calc(100vw - 24px)}.tABNoa_viewArea{flex-direction:column;flex:1;min-height:0;display:flex}.tABNoa_widthHandle{z-index:0;width:min(10px, calc((100% - var(--qilin-chat-content-width)) / 2 - 24px - 24px));cursor:col-resize;position:absolute;top:0;bottom:0}.tABNoa_widthHandle[data-side=left]{right:calc(50% + var(--qilin-chat-content-width) / 2 + 24px)}.tABNoa_widthHandle[data-side=right]{left:calc(50% + var(--qilin-chat-content-width) / 2 + 24px)}.tABNoa_widthHandle:after{content:\"\";background:linear-gradient(to bottom, transparent calc(var(--qilin-width-handle-pointer-y,50%) - 36px), var(--qilin-alias-scrollbar-bg-l1) calc(var(--qilin-width-handle-pointer-y,50%) - 8px), var(--qilin-alias-scrollbar-bg-l1) calc(var(--qilin-width-handle-pointer-y,50%) + 8px), transparent calc(var(--qilin-width-handle-pointer-y,50%) + 36px));opacity:0;pointer-events:none;border-radius:2px;width:2px;position:absolute;top:0;bottom:0}.tABNoa_widthHandle[data-side=left]:after{right:4px}.tABNoa_widthHandle[data-side=right]:after{left:4px}.tABNoa_widthHandle:hover:after,.tABNoa_widthHandle[data-dragging]:after{opacity:1}.tABNoa_widthHandle[data-dragging]{z-index:8}.tABNoa_composerStack{--qilin-composer-stack-gap:6px;gap:var(--qilin-composer-stack-gap);flex-direction:column;display:flex}.tABNoa_composerSeat{--qilin-composer-text-max-height:336px;flex-direction:column;flex:none;display:flex}.tABNoa_root[data-phase=active]{overflow:hidden}.tABNoa_root[data-phase=active] .tABNoa_header{flex:none}.tABNoa_body{--qilin-chat-content-width:var(--qilin-chat-user-width,clamp(680px, calc(var(--qilin-conversation-column-width,0px) * .64), 920px));--qilin-composer-card-max-width:calc(var(--qilin-chat-content-width) + 32px);--qilin-composer-side-clearance:16px;--qilin-composer-dock-inset:8px;flex-direction:column;flex:1;min-height:0;display:flex;position:relative}.tABNoa_embeddedBody{--qilin-chat-content-width:min(calc(100% - 32px), 920px);--qilin-composer-card-max-width:min(calc(100% - 16px), 952px);--qilin-composer-side-clearance:8px;--qilin-composer-dock-inset:8px;overflow:hidden}.tABNoa_scrollBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;margin-right:2px;display:flex;overflow-y:auto}.tABNoa_scrollBody::-webkit-scrollbar-track{margin:2px}.tABNoa_root[data-phase=active] .tABNoa_viewArea,.tABNoa_embeddedBody[data-content-phase=active] .tABNoa_viewArea{flex:1 0 auto;min-height:auto}.tABNoa_root[data-phase=active] .tABNoa_composerSeat,.tABNoa_embeddedBody[data-content-phase=active] .tABNoa_composerSeat{z-index:7;background:linear-gradient(180deg, color-mix(in srgb, var(--qilin-alias-bg-base) 0%, transparent) 0px, var(--qilin-alias-bg-base) 36px);position:sticky;bottom:0}.tABNoa_root[data-phase=active] .tABNoa_composerSeat:has([data-trigger-menu]){z-index:9}.tABNoa_composerHero{width:min(calc(var(--qilin-composer-card-max-width) + 2 * var(--qilin-composer-side-clearance)), 100%);z-index:1;align-self:center;gap:8px;padding-bottom:32px}.tABNoa_heroWorkspaceRow{align-items:center;gap:2px;min-width:0;margin-top:4px;padding:0 16px 0 20px;display:flex}.tABNoa_heroOptions{flex:none;align-items:center;gap:2px;min-width:0;margin-left:auto;display:flex}.tABNoa_heroOptions:empty{display:none}.tABNoa_root[data-phase=hero] .tABNoa_scrollBody,.tABNoa_embeddedBody[data-content-phase=hero] .tABNoa_scrollBody{justify-content:center;overflow-y:auto}.tABNoa_root[data-phase=settling] .tABNoa_composerSeat,.tABNoa_embeddedBody[data-content-phase=settling] .tABNoa_composerSeat{visibility:hidden}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_header:has(.tABNoa_tabs){grid-template-rows:30px auto;grid-template-columns:auto minmax(0,1fr);align-items:start;column-gap:0;display:grid}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_header:has(.tABNoa_tabs)>div:not(.tABNoa_headerLeading):has(.tABNoa_titleRow){display:contents}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_headerLeading{grid-area:1/1}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_titleRow{grid-area:1/2}html[data-platform=darwin] [data-sidebar-collapsed] .tABNoa_tabs{grid-area:2/1/auto/-1}";
20949
21170
  const tagId$4 = "@qilin-agent/client-ui-conversation/ConversationRoot.module.css";
20950
21171
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
20951
21172
  const tag = document.createElement("style");
@@ -20979,10 +21200,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20979
21200
  "scrollBody": "tABNoa_scrollBody",
20980
21201
  "tab": "tABNoa_tab",
20981
21202
  "tabActive": "tABNoa_tabActive",
21203
+ "tabLabel": "tABNoa_tabLabel",
20982
21204
  "tabs": "tABNoa_tabs",
20983
21205
  "titleCluster": "tABNoa_titleCluster",
20984
21206
  "titleRow": "tABNoa_titleRow",
20985
21207
  "viewArea": "tABNoa_viewArea",
21208
+ "viewTabs": "tABNoa_viewTabs",
21209
+ "viewsMore": "tABNoa_viewsMore",
21210
+ "viewsMoreActive": "tABNoa_viewsMoreActive",
21211
+ "viewsMoreAnchor": "tABNoa_viewsMoreAnchor",
21212
+ "viewsMoreMenu": "tABNoa_viewsMoreMenu",
20986
21213
  "widthHandle": "tABNoa_widthHandle"
20987
21214
  };
20988
21215
  //#endregion
@@ -21212,19 +21439,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21212
21439
  return (0, react_jsx_runtime.jsx)(ConversationMainPanel, { ...props });
21213
21440
  }
21214
21441
  //#endregion
21215
- //#region ../../util/workspace-path/src/index.ts
21216
- /**
21217
- * Read the final non-empty segment of a Workspace path for display.
21218
- * Workspace-label surfaces use this helper instead of deriving another basename.
21219
- * @param path - Workspace directory path using POSIX or Windows separators.
21220
- * @returns the final segment, or an empty string for a separator-only path.
21221
- */
21222
- function workspaceTitleOf(path) {
21223
- const trimmed = path.replace(/[/\\]+$/, "");
21224
- const separator = Math.max(trimmed.lastIndexOf("/"), trimmed.lastIndexOf("\\"));
21225
- return trimmed.slice(separator + 1);
21226
- }
21227
- //#endregion
21228
21442
  //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-conversation/src/client/skeleton/HeroShell.module.css.mjs
21229
21443
  const css$3 = ".ew0MzG_root{justify-content:center;align-items:center;min-width:0;height:100%;padding:0 24px;display:flex;position:relative;overflow:hidden}.ew0MzG_watermark{color:var(--qilin-alias-label-primary);letter-spacing:-.04em;white-space:nowrap;opacity:.06;pointer-events:none;user-select:none;justify-content:center;font-size:clamp(64px,18vw,224px);font-weight:800;line-height:1;display:flex;position:absolute;top:50%;left:0;right:0;transform:translateY(-50%)}.ew0MzG_stack{width:100%;max-width:var(--qilin-composer-card-max-width);flex-direction:column;align-items:stretch;gap:12px;display:flex;overflow:visible}.ew0MzG_mark{justify-content:center;align-items:center;display:flex}.ew0MzG_greeting{color:var(--qilin-alias-label-secondary);letter-spacing:-.01em;text-align:center;text-wrap:balance;margin:0;font-size:18px;font-weight:500;line-height:26px}.ew0MzG_tagline{color:var(--qilin-alias-label-primary);letter-spacing:-.02em;text-align:center;text-wrap:balance;margin:0;font-size:clamp(24px,3.4vw,40px);font-weight:600;line-height:1.2}.ew0MzG_body{flex-direction:column;gap:12px;min-width:0;display:flex;position:relative;overflow:visible}.ew0MzG_body>*{z-index:1;position:relative}.ew0MzG_body>.ew0MzG_workspaceRow{z-index:10;align-items:center;min-width:0;padding-left:8px;display:flex}.ew0MzG_workspace{max-width:min(100%,360px);min-height:28px;color:var(--qilin-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:16px;align-items:center;gap:4px;padding:0 8px;font-size:13px;font-weight:500;line-height:20px;display:inline-flex}.ew0MzG_workspace:not(:disabled):hover,.ew0MzG_workspace[aria-expanded=true]{background:var(--qilin-alias-interactive-bg-hover)}.ew0MzG_workspace:disabled{cursor:default}.ew0MzG_folder{color:var(--qilin-alias-label-primary);flex:none}.ew0MzG_workspaceLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.ew0MzG_chevron{color:var(--qilin-alias-label-caption);flex:none}.ew0MzG_modalInput{box-sizing:border-box;border:.5px solid var(--qilin-alias-border-l4);width:100%;height:44px;color:var(--qilin-alias-label-primary);background:0 0;border-radius:22px;outline:none;padding:7px 14px;font-size:14px;font-weight:400;line-height:22px}.ew0MzG_modalInput::placeholder{color:var(--qilin-alias-label-caption)}.ew0MzG_modalInput:disabled{color:var(--qilin-alias-label-dimmed)}.ew0MzG_modalAction{min-width:72px}.ew0MzG_modalError{color:var(--qilin-alias-state-error-primary);margin-top:8px;font-size:12px;line-height:18px}";
21230
21444
  const tagId$3 = "@qilin-agent/client-ui-conversation/HeroShell.module.css";
@@ -21285,10 +21499,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21285
21499
  "aria-expanded": menuOpen,
21286
21500
  onClick,
21287
21501
  children: [
21288
- label === void 0 ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconFolderClose16, {
21502
+ label === void 0 ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconFolderCloseRegular, {
21289
21503
  className: HeroShell_module_css_default.folder,
21290
21504
  size: 16
21291
- }) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconFolderOpen16, {
21505
+ }) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconFolderOpenRegular, {
21292
21506
  className: HeroShell_module_css_default.folder,
21293
21507
  size: 16
21294
21508
  }),
@@ -21296,7 +21510,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21296
21510
  className: HeroShell_module_css_default.workspaceLabel,
21297
21511
  children: label ?? t("hero.chooseWorkspace")
21298
21512
  }),
21299
- (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, {
21513
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, {
21300
21514
  className: HeroShell_module_css_default.chevron,
21301
21515
  size: 12
21302
21516
  })
@@ -21527,6 +21741,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21527
21741
  return (selectedId === null ? void 0 : tabs.find((view) => view.id === selectedId)) ?? tabs.find((view) => view.id === DEFAULT_VIEW_ID);
21528
21742
  }
21529
21743
  //#endregion
21744
+ //#region lib/types/client/view-pins.js
21745
+ /** In-memory pin choices for the Conversation View tabs. */
21746
+ /** View whose tab always shows and never enters the customization list. */
21747
+ const FIXED_VIEW_ID = "chat";
21748
+ const NO_VIEWS = [];
21749
+ /**
21750
+ * Create the in-memory View pin list; the snapshot keeps its reference until the list changes.
21751
+ * @returns Unpinned View ids and the pin mutation.
21752
+ */
21753
+ function createViewPins() {
21754
+ const store = (0, _qilin_agent_client_store.createSnapshotStore)({ unpinned: NO_VIEWS });
21755
+ return {
21756
+ unpinned: {
21757
+ getSnapshot: () => store.getSnapshot().unpinned,
21758
+ subscribe: (listener) => store.subscribe(listener)
21759
+ },
21760
+ setPinned: (id, pinned) => {
21761
+ const current = store.getSnapshot().unpinned;
21762
+ if (id === "chat" || pinned !== current.includes(id)) return;
21763
+ store.set({ unpinned: pinned ? current.filter((entry) => entry !== id) : [...current, id] });
21764
+ }
21765
+ };
21766
+ }
21767
+ //#endregion
21530
21768
  //#region lib/types/client/skeleton/DefaultConversationViews.js
21531
21769
  /**
21532
21770
  * Renders the active Session view inside the resident scrollport and keeps
@@ -21560,6 +21798,42 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21560
21798
  //#endregion
21561
21799
  //#region lib/types/client/skeleton/ConversationSession.js
21562
21800
  /** Strict per-session header/body content inserted into the resident conversation layout. */
21801
+ /** The View tab row's More launcher; its menu rows come from `conversation.session.header.views.actions`. */
21802
+ function ViewsMoreMenu({ label, current, entries, onOpen, onPinnedChange, renderSlot }) {
21803
+ const [open, setOpen] = (0, react.useState)(false);
21804
+ const onDismiss = () => {
21805
+ setOpen(false);
21806
+ };
21807
+ return (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Menu, {
21808
+ open,
21809
+ onClose: onDismiss,
21810
+ portal: true,
21811
+ autoFocus: true,
21812
+ className: ConversationRoot_module_css_default.viewsMoreAnchor,
21813
+ listClassName: ConversationRoot_module_css_default.viewsMoreMenu,
21814
+ anchor: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
21815
+ label,
21816
+ portal: true,
21817
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Button, {
21818
+ size: "sm",
21819
+ className: clsx(ConversationRoot_module_css_default.viewsMore, current && ConversationRoot_module_css_default.viewsMoreActive),
21820
+ "aria-label": label,
21821
+ "aria-haspopup": "menu",
21822
+ "aria-expanded": open,
21823
+ onClick: () => {
21824
+ setOpen((value) => !value);
21825
+ },
21826
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconEllipsisOutlineRegular, { size: 13 })
21827
+ })
21828
+ }),
21829
+ children: renderSlot("conversation.session.header.views.actions", {
21830
+ entries,
21831
+ onOpen,
21832
+ onPinnedChange,
21833
+ onDismiss
21834
+ })
21835
+ });
21836
+ }
21563
21837
  function deriveAncestry(list, id) {
21564
21838
  const chain = [];
21565
21839
  const seen = /* @__PURE__ */ new Set();
@@ -21591,11 +21865,44 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21591
21865
  * @param props - Session identity, parent-owned chrome visibility, view ledger, navigation, render, and locale shares.
21592
21866
  * @returns the title row and, with more than one View, the tab strip.
21593
21867
  */
21594
- function ConversationSessionHeader({ sessionId, hideChrome, useSessions, useConversationViews, useStore, renderSlot, open, selectView, t }) {
21868
+ function ConversationSessionHeader({ sessionId, hideChrome, useSessions, useConversationViews, useStore, renderSlot, open, selectView, setPinned, t, useEntryPins, useEntryActions }) {
21595
21869
  const tabs = useConversationViews((value) => value);
21596
21870
  const active = resolveActiveView(tabs, useStore((s) => s.view));
21597
21871
  const ancestry = useSessions((s) => deriveAncestry(s, sessionId), equalBreadcrumbs);
21872
+ const unpinned = useEntryPins((ids) => ids);
21873
+ const hasEntryActions = useEntryActions((registered) => registered);
21598
21874
  const showTabs = !hideChrome && tabs.length > 1;
21875
+ const tabRow = (0, react.useRef)(null);
21876
+ const [visibleViewLimit, setVisibleViewLimit] = (0, react.useState)(1);
21877
+ (0, react.useLayoutEffect)(() => {
21878
+ const row = tabRow.current;
21879
+ if (row === null || !hasEntryActions) return;
21880
+ const updateLimit = () => {
21881
+ setVisibleViewLimit(Math.max(1, Math.floor((row.clientWidth - 48) / 120)));
21882
+ };
21883
+ updateLimit();
21884
+ if (typeof ResizeObserver === "undefined") return;
21885
+ const observer = new ResizeObserver(updateLimit);
21886
+ observer.observe(row);
21887
+ return () => {
21888
+ observer.disconnect();
21889
+ };
21890
+ }, [showTabs, hasEntryActions]);
21891
+ const { visibleTabs, moreTabs } = (0, react.useMemo)(() => {
21892
+ const preferred = [...tabs.filter((tab) => tab.id === FIXED_VIEW_ID), ...tabs.filter((tab) => tab.id !== "chat" && !unpinned.includes(tab.id))];
21893
+ const visibleTabs = hasEntryActions ? preferred.slice(0, visibleViewLimit) : preferred;
21894
+ const visibleIds = new Set(visibleTabs.map((tab) => tab.id));
21895
+ return {
21896
+ visibleTabs,
21897
+ moreTabs: tabs.filter((tab) => !visibleIds.has(tab.id))
21898
+ };
21899
+ }, [
21900
+ tabs,
21901
+ unpinned,
21902
+ hasEntryActions,
21903
+ visibleViewLimit
21904
+ ]);
21905
+ const currentInMore = moreTabs.some((tab) => tab.id === active?.id);
21599
21906
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
21600
21907
  className: ConversationRoot_module_css_default.titleRow,
21601
21908
  children: [!hideChrome && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
@@ -21645,20 +21952,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21645
21952
  "data-conversation-header-corner": "",
21646
21953
  children: renderSlot("conversation.session.header.corner", {})
21647
21954
  })]
21648
- }), showTabs && (0, react_jsx_runtime.jsx)("div", {
21955
+ }), showTabs && (0, react_jsx_runtime.jsxs)("div", {
21956
+ ref: tabRow,
21649
21957
  className: ConversationRoot_module_css_default.tabs,
21650
- role: "tablist",
21651
- "data-conversation-tabs": "",
21652
- children: tabs.map((viewTab) => (0, react_jsx_runtime.jsx)("button", {
21653
- type: "button",
21654
- role: "tab",
21655
- "aria-selected": viewTab.id === active?.id,
21656
- className: clsx(ConversationRoot_module_css_default.tab, viewTab.id === active?.id && ConversationRoot_module_css_default.tabActive),
21657
- onClick: () => {
21658
- selectView(viewTab.id);
21659
- },
21660
- children: viewTab.label
21661
- }, viewTab.id))
21958
+ children: [(0, react_jsx_runtime.jsx)("div", {
21959
+ className: ConversationRoot_module_css_default.viewTabs,
21960
+ role: "tablist",
21961
+ "data-conversation-tabs": "",
21962
+ children: visibleTabs.map((viewTab) => (0, react_jsx_runtime.jsx)("button", {
21963
+ type: "button",
21964
+ role: "tab",
21965
+ "aria-selected": viewTab.id === active?.id,
21966
+ className: clsx(ConversationRoot_module_css_default.tab, viewTab.id === active?.id && ConversationRoot_module_css_default.tabActive),
21967
+ onClick: () => {
21968
+ selectView(viewTab.id);
21969
+ },
21970
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
21971
+ label: viewTab.label,
21972
+ portal: true,
21973
+ children: (0, react_jsx_runtime.jsx)("span", {
21974
+ className: ConversationRoot_module_css_default.tabLabel,
21975
+ children: viewTab.label
21976
+ })
21977
+ })
21978
+ }, viewTab.id))
21979
+ }), hasEntryActions && (0, react_jsx_runtime.jsx)(ViewsMoreMenu, {
21980
+ label: currentInMore && active !== void 0 ? t("session.moreViewsCurrent", { name: active.label }) : t("session.moreViews"),
21981
+ current: currentInMore,
21982
+ entries: moreTabs.map((viewTab) => ({
21983
+ id: viewTab.id,
21984
+ label: viewTab.label,
21985
+ pinned: !unpinned.includes(viewTab.id),
21986
+ active: viewTab.id === active?.id
21987
+ })),
21988
+ onOpen: selectView,
21989
+ onPinnedChange: setPinned,
21990
+ renderSlot
21991
+ })]
21662
21992
  })] });
21663
21993
  }
21664
21994
  /**
@@ -21853,8 +22183,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21853
22183
  }, 4), editor.registerCommand(Je$2, (event) => {
21854
22184
  const clipboardData = event.clipboardData ?? null;
21855
22185
  if (clipboardData === null) return false;
21856
- const files = Array.from(clipboardData.items).filter((item) => item.kind === "file").map((item) => item.getAsFile()).filter((file) => file !== null);
21857
- if (files.length > 0) handlers.intakeFiles(files);
22186
+ const files = [];
22187
+ const directories = /* @__PURE__ */ new Set();
22188
+ for (const item of clipboardData.items) {
22189
+ if (item.kind !== "file") continue;
22190
+ const file = item.getAsFile();
22191
+ if (file === null) continue;
22192
+ files.push(file);
22193
+ if (typeof item.webkitGetAsEntry === "function" && item.webkitGetAsEntry()?.isDirectory === true) directories.add(file);
22194
+ }
22195
+ if (files.length > 0) handlers.intakeFiles(files, directories.size === 0 ? void 0 : directories);
21858
22196
  const text = clipboardData.getData("text/plain");
21859
22197
  if (text === "") {
21860
22198
  if (files.length === 0) return false;
@@ -21966,8 +22304,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21966
22304
  }
21967
22305
  keyboard.submit(resolveSubmitMode(g.busyEnter, g.running, accelerated ? "accelerated" : "enter", g.steeringAvailable));
21968
22306
  },
21969
- intakeFiles: (files) => {
21970
- gate.current.intakeFiles(files);
22307
+ intakeFiles: (files, directories) => {
22308
+ gate.current.intakeFiles(files, directories);
21971
22309
  },
21972
22310
  pasteText: (text) => {
21973
22311
  if (gate.current.machineBusy || gate.current.locked) return;
@@ -22297,7 +22635,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22297
22635
  }
22298
22636
  //#endregion
22299
22637
  //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-conversation/src/client/skeleton/InputBar.module.css.mjs
22300
- const css$1 = ".GAmSYG_root{padding:0 var(--qilin-composer-side-clearance) 4px;flex-direction:column;align-items:center;display:flex}.GAmSYG_dock{justify-content:center;align-items:center;gap:12px;max-width:100%;padding-top:4px;display:flex}.GAmSYG_hero .GAmSYG_dock:empty{display:none}.GAmSYG_hero{padding:0 var(--qilin-composer-side-clearance)}.GAmSYG_notice{width:100%;max-width:var(--qilin-composer-card-max-width);background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-secondary);border-radius:8px;margin-bottom:6px;padding:4px 8px;font-size:12px;line-height:18px}.GAmSYG_card{box-sizing:border-box;width:100%;max-width:var(--qilin-composer-card-max-width);--qilin-elevation-stroke-color:var(--qilin-alias-border-l2);background:var(--qilin-specific-input-major);box-shadow:var(--qilin-elevation-soft);font-size:var(--qilin-content-font-size,14px);line-height:calc(24px + var(--qilin-content-font-delta,0px));--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);border:0;border-radius:22px;flex-direction:column;gap:12px;padding-top:8px;display:flex;position:relative}.GAmSYG_cardWorkspaceTrigger{--qilin-elevation-stroke-color:transparent;cursor:pointer}.GAmSYG_cardWorkspaceTrigger:after{content:\"\";background:var(--qilin-alias-border-l4);pointer-events:none;border-radius:22px;transition:background-color .1s;position:absolute;inset:-1px;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\");mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\")}.GAmSYG_cardWorkspaceTrigger :disabled{pointer-events:none}.GAmSYG_cardWorkspaceTrigger:hover:after{background:var(--qilin-alias-state-business-primary)}.GAmSYG_accessory{align-items:center;gap:8px;padding:10px 12px 0;display:flex}.GAmSYG_overlayAnchor{height:0;position:absolute;inset:0 0 auto}.GAmSYG_scroll{max-height:var(--qilin-composer-text-max-height);margin-right:4px;overflow-y:auto}.GAmSYG_scroll::-webkit-scrollbar-track{margin-top:8px}.GAmSYG_grow{position:relative}.GAmSYG_pending{corner-shape:round;background:var(--qilin-alias-state-business-primary);border-radius:50%;width:8px;height:8px;animation:1s ease-in-out infinite alternate GAmSYG_input-pending}@keyframes GAmSYG_input-pending{0%{opacity:.35}to{opacity:1}}.GAmSYG_input{box-sizing:border-box;min-height:36px;font-family:var(--qilin-font-family);font-size:inherit;line-height:inherit;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;color:var(--qilin-alias-label-primary);caret-color:var(--qilin-alias-state-business-primary);outline:none;padding:4px 8px 0 14px}.GAmSYG_input p{margin:0}.GAmSYG_input p:last-child:after{content:var(--qilin-composer-hint);color:var(--qilin-alias-label-caption)}.GAmSYG_input[data-composer-composing] p:last-child:after{content:none}.GAmSYG_input[data-composer-chip-selected]{caret-color:#0000}.GAmSYG_input[data-composer-composing]+.GAmSYG_placeholder{visibility:hidden}.GAmSYG_placeholder{color:var(--qilin-alias-label-caption);white-space:nowrap;text-overflow:ellipsis;pointer-events:none;user-select:none;position:absolute;inset:4px 8px auto 14px;overflow:hidden}.GAmSYG_inputDisabled{color:var(--qilin-alias-label-tertiary);cursor:not-allowed}.GAmSYG_input[aria-haspopup=menu]{cursor:pointer}.GAmSYG_hero .GAmSYG_input{min-height:52px}.GAmSYG_hero .GAmSYG_placeholder{white-space:normal;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.GAmSYG_row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;min-width:0;padding:2px 8px 6px;display:flex;container-type:inline-size}.GAmSYG_row[data-model-compact]{--dsh-composer-model-text-display:none;--dsh-composer-model-icon-display:block}.GAmSYG_tools,.GAmSYG_modes,.GAmSYG_trailing{align-items:center;min-width:0;display:flex}.GAmSYG_tools,.GAmSYG_modes{gap:12px}.GAmSYG_trailing{flex:none;gap:12px;margin-left:auto}.GAmSYG_add{corner-shape:round;background:var(--qilin-specific-selector);width:28px;height:28px;color:var(--qilin-alias-label-primary);cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;display:grid}.GAmSYG_add:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-solid)}.GAmSYG_add:disabled{opacity:.5;cursor:default}.GAmSYG_select{max-width:220px;height:28px;color:var(--qilin-alias-label-secondary);white-space:nowrap;cursor:pointer;appearance:none;background-color:#0000;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 4px center;background-repeat:no-repeat;background-size:12px 12px;border:none;border-radius:8px;outline:none;padding:0 20px 0 8px;font-size:13px;font-weight:500;line-height:20px}.GAmSYG_select:hover:not(:disabled){background-color:var(--qilin-alias-interactive-bg-hover)}.GAmSYG_select:disabled{opacity:.5;cursor:default}.GAmSYG_primary{corner-shape:round;background:var(--qilin-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;width:34px;height:34px;transition:background-color .1s;display:grid;transform:translateY(-2px)}.GAmSYG_primary:hover:not(:disabled){background:var(--qilin-alias-button-info-hover)}.GAmSYG_primary:disabled{opacity:.4;cursor:default}.GAmSYG_retry{color:inherit;cursor:pointer;background:0 0;border:1px solid;border-radius:4px;margin-left:8px;padding:1px 8px;font-size:12px}.GAmSYG_standardControls{align-items:center;gap:12px;min-width:0;display:flex}.GAmSYG_tools[hidden],.GAmSYG_standardControls[hidden]{display:none}.GAmSYG_trailingActive{flex:1;margin-left:0}.GAmSYG_activity{flex:none;align-items:center;display:flex}.GAmSYG_activity:empty{display:none}.GAmSYG_activityExpanded{flex:1;min-width:0}";
22638
+ const css$1 = ".GAmSYG_root{padding:0 var(--qilin-composer-side-clearance) 4px;flex-direction:column;align-items:center;display:flex}.GAmSYG_dock{justify-content:center;align-items:center;gap:12px;max-width:100%;padding-top:4px;display:flex}.GAmSYG_hero .GAmSYG_dock:empty{display:none}.GAmSYG_hero{padding:0 var(--qilin-composer-side-clearance)}.GAmSYG_notice{width:100%;max-width:var(--qilin-composer-card-max-width);border-radius:var(--qilin-radius-md);background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-secondary);margin-bottom:6px;padding:4px 8px;font-size:12px;line-height:18px}.GAmSYG_card{box-sizing:border-box;width:100%;max-width:var(--qilin-composer-card-max-width);--qilin-elevation-stroke-color:var(--qilin-alias-border-l2);border-radius:var(--qilin-radius-panel);background:var(--qilin-specific-input-major);box-shadow:var(--qilin-elevation-soft);font-size:var(--qilin-content-font-size,14px);line-height:calc(24px + var(--qilin-content-font-delta,0px));--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);border:0;flex-direction:column;gap:12px;padding-top:8px;display:flex;position:relative}.GAmSYG_cardWorkspaceTrigger{--qilin-elevation-stroke-color:transparent;cursor:pointer}.GAmSYG_cardWorkspaceTrigger:after{content:\"\";box-sizing:border-box;border-radius:var(--qilin-radius-panel);color:var(--qilin-alias-border-l4);pointer-events:none;border:1px dashed;transition:color .1s;position:absolute;inset:0}.GAmSYG_cardWorkspaceTrigger :disabled{pointer-events:none}.GAmSYG_cardWorkspaceTrigger:hover:after{color:var(--qilin-alias-state-business-primary)}.GAmSYG_accessory{align-items:center;gap:8px;padding:10px 12px 0;display:flex}.GAmSYG_overlayAnchor{height:0;position:absolute;inset:0 0 auto}.GAmSYG_scroll{max-height:var(--qilin-composer-text-max-height);margin-right:4px;overflow-y:auto}.GAmSYG_scroll::-webkit-scrollbar-track{margin-top:8px}.GAmSYG_grow{position:relative}.GAmSYG_pending{corner-shape:round;background:var(--qilin-alias-state-business-primary);border-radius:50%;width:8px;height:8px;animation:1s ease-in-out infinite alternate GAmSYG_input-pending}@keyframes GAmSYG_input-pending{0%{opacity:.35}to{opacity:1}}.GAmSYG_input{box-sizing:border-box;min-height:36px;font-family:var(--qilin-font-family);font-size:inherit;line-height:inherit;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;color:var(--qilin-alias-label-primary);caret-color:var(--qilin-alias-state-business-primary);outline:none;padding:4px 8px 0 14px}.GAmSYG_input p{margin:0}.GAmSYG_input p:last-child:after{content:var(--qilin-composer-hint);color:var(--qilin-alias-label-caption)}.GAmSYG_input[data-composer-composing] p:last-child:after{content:none}.GAmSYG_input[data-composer-chip-selected]{caret-color:#0000}.GAmSYG_input[data-composer-composing]+.GAmSYG_placeholder{visibility:hidden}.GAmSYG_placeholder{color:var(--qilin-alias-label-caption);white-space:nowrap;text-overflow:ellipsis;pointer-events:none;user-select:none;position:absolute;inset:4px 8px auto 14px;overflow:hidden}.GAmSYG_inputDisabled{color:var(--qilin-alias-label-tertiary);cursor:not-allowed}.GAmSYG_input[aria-haspopup=menu]{cursor:pointer}.GAmSYG_hero .GAmSYG_input{min-height:52px}.GAmSYG_hero .GAmSYG_placeholder{white-space:normal;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box}.GAmSYG_row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;min-width:0;padding:2px 8px 6px;display:flex;container-type:inline-size}.GAmSYG_row[data-model-compact]{--dsh-composer-model-text-display:none;--dsh-composer-model-icon-display:block}.GAmSYG_tools,.GAmSYG_modes,.GAmSYG_trailing{align-items:center;min-width:0;display:flex}.GAmSYG_tools,.GAmSYG_modes{gap:12px}.GAmSYG_trailing{flex:none;gap:12px;margin-left:auto}@container (width<=560px){.GAmSYG_tools,.GAmSYG_modes,.GAmSYG_trailing{gap:8px}}.GAmSYG_add{corner-shape:round;background:var(--qilin-specific-selector);width:28px;height:28px;color:var(--qilin-alias-label-primary);cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;display:grid}.GAmSYG_add:hover:not(:disabled){background:var(--qilin-alias-interactive-bg-hover-solid)}.GAmSYG_add:disabled{opacity:.5;cursor:default}.GAmSYG_select{border-radius:var(--qilin-radius-sm);max-width:220px;height:28px;color:var(--qilin-alias-label-secondary);white-space:nowrap;cursor:pointer;appearance:none;background-color:#0000;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 4px center;background-repeat:no-repeat;background-size:12px 12px;border:none;outline:none;padding:0 20px 0 8px;font-size:13px;font-weight:500;line-height:20px}.GAmSYG_select:hover:not(:disabled){background-color:var(--qilin-alias-interactive-bg-hover)}.GAmSYG_select:disabled{opacity:.5;cursor:default}.GAmSYG_primary{corner-shape:round;background:var(--qilin-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;width:34px;height:34px;transition:background-color .1s;display:grid;transform:translateY(-2px)}.GAmSYG_primary:hover:not(:disabled){background:var(--qilin-alias-button-info-hover)}.GAmSYG_primary:disabled{opacity:.4;cursor:default}.GAmSYG_retry{border-radius:var(--qilin-radius-sm);color:inherit;cursor:pointer;background:0 0;border:1px solid;margin-left:8px;padding:1px 8px;font-size:12px}.GAmSYG_standardControls{align-items:center;gap:12px;min-width:0;display:flex}.GAmSYG_tools[hidden],.GAmSYG_standardControls[hidden]{display:none}.GAmSYG_trailingActive{flex:1;margin-left:0}.GAmSYG_activity{flex:none;align-items:center;display:flex}.GAmSYG_activity:empty{display:none}.GAmSYG_activityExpanded{flex:1;min-width:0}";
22301
22639
  const tagId$1 = "@qilin-agent/client-ui-conversation/InputBar.module.css";
22302
22640
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
22303
22641
  const tag = document.createElement("style");
@@ -22351,10 +22689,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22351
22689
  * The no-session state renders the SAME div inert as the Workspace-picker
22352
22690
  * trigger instead of a parallel tree.
22353
22691
  */
22354
- const InputBar = (0, react.memo)(function InputBar({ useSession, useInput, inputActions, keyboard, addFiles, removeAttachment, resolveDraftAttachments, retryFileUpload, toggleCommandMenu, stop, t, renderSlot, useBusyEnter, useFileUploads, useNotices, useLexicon, useMenuLauncher, useProjection, sessionId, variant, disabled: inert = false, blocked, workspacePickerOpen = false, onRequestWorkspace, placeholder, accessory }) {
22692
+ const InputBar = (0, react.memo)(function InputBar({ useSession, useInput, inputActions, keyboard, addFiles, removeAttachment, resolveDraftAttachments, retryFileUpload, toggleCommandMenu, stop, t, renderSlot, useBusyEnter, useFileUploads, useNotices, useLexicon, useMenuLauncher, useStopShortcut, useProjection, sessionId, variant, disabled: inert = false, blocked, workspacePickerOpen = false, onRequestWorkspace, placeholder, accessory }) {
22355
22693
  const input = useInput((s) => s);
22356
22694
  const notice = useNotices((s) => s);
22357
22695
  const busyEnter = useBusyEnter((s) => s);
22696
+ const stopKeys = useStopShortcut((keys) => keys);
22358
22697
  const commandMenuOpen = useMenuLauncher((source) => source === "command");
22359
22698
  const [activity, setActivity] = (0, react.useState)(false);
22360
22699
  (0, react.useEffect)(() => {
@@ -22448,10 +22787,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22448
22787
  (0, react.useEffect)(() => {
22449
22788
  return installDraftWheel(scrollRef);
22450
22789
  }, []);
22451
- const intakeFiles = (0, react.useCallback)((files) => {
22790
+ const intakeFiles = (0, react.useCallback)((files, directories) => {
22452
22791
  if (locked || machineBusy || subagent !== null && !continuable || addFiles === void 0 || files.length === 0) return;
22453
22792
  const rejected = (() => {
22454
- if (continuable && files.some((file) => !isImageMediaType(file.type))) return t("image.unsupportedType");
22793
+ if (continuable && files.some((file) => directories?.has(file) || !isImageMediaType(file.type))) return t("image.unsupportedType");
22455
22794
  if (imageLimits !== void 0) {
22456
22795
  const mediaTypes = imageLimits.mediaTypes;
22457
22796
  const images = files.filter((file) => mediaTypes.includes(file.type));
@@ -22460,7 +22799,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22460
22799
  if (images.some((file) => file.size > imageLimits.maxImageBytes)) return t("image.fileTooLarge", { size: imageSizeText(imageLimits.maxImageBytes) });
22461
22800
  if (imageAttachments.reduce((sum, attachment) => sum + attachment.file.size, 0) + images.reduce((sum, file) => sum + file.size, 0) > imageLimits.maxMessageImageBytes) return t("image.totalTooLarge", { size: imageSizeText(imageLimits.maxMessageImageBytes) });
22462
22801
  }
22463
- return addFiles(files);
22802
+ return addFiles(files, directories);
22464
22803
  })();
22465
22804
  if (rejected !== null) showToast(rejected);
22466
22805
  }, [
@@ -22571,7 +22910,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22571
22910
  children: [
22572
22911
  toast !== null && (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Toast, {
22573
22912
  text: toast.text,
22574
- icon: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconWarningOutline16, {}),
22913
+ icon: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconWarningOutlineRegular, {}),
22575
22914
  anchor: cardRef.current,
22576
22915
  onDone: dismissToast
22577
22916
  }, toast.seq),
@@ -22650,7 +22989,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22650
22989
  disabled: locked || toggleCommandMenu === void 0,
22651
22990
  onMouseDown: keepFocus,
22652
22991
  onClick: onToggleCommandMenu,
22653
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutline16, { size: 14 })
22992
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPlusOutlineMedium, { size: 14 })
22654
22993
  })
22655
22994
  }),
22656
22995
  (0, react_jsx_runtime.jsx)("input", {
@@ -22684,6 +23023,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22684
23023
  }),
22685
23024
  interruptible && (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
22686
23025
  label: t("input.stop"),
23026
+ shortcutKeys: stopKeys,
22687
23027
  side: "top",
22688
23028
  delayMs: 500,
22689
23029
  disabled: stop === void 0,
@@ -22711,7 +23051,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22711
23051
  })
22712
23052
  }),
22713
23053
  (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
22714
- label: primaryLabel,
23054
+ label: primaryStops ? t("input.stop") : primaryLabel,
23055
+ shortcutKeys: primaryStops ? stopKeys : void 0,
22715
23056
  side: "top",
22716
23057
  delayMs: 500,
22717
23058
  disabled: primaryDisabled,
@@ -22754,6 +23095,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22754
23095
  }),
22755
23096
  (0, react_jsx_runtime.jsxs)("div", {
22756
23097
  className: InputBar_module_css_default.dock,
23098
+ "data-composer-dock": true,
22757
23099
  children: [variant === "composer" && input !== void 0 && sessionId !== void 0 ? renderSlot("conversation.composer.dock", {}) : null, activity ? null : (0, react_jsx_runtime.jsx)(ContextMeter, {
22758
23100
  useProjection,
22759
23101
  t
@@ -22908,7 +23250,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22908
23250
  (0, react_jsx_runtime.jsx)("span", {
22909
23251
  className: TodoPanel_module_css_default.lead,
22910
23252
  "aria-hidden": true,
22911
- children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChecklistOutline14, {})
23253
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChecklistOutlineRegular, {})
22912
23254
  }),
22913
23255
  (0, react_jsx_runtime.jsx)("span", {
22914
23256
  className: TodoPanel_module_css_default.title,
@@ -22921,7 +23263,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22921
23263
  (0, react_jsx_runtime.jsx)("span", {
22922
23264
  className: TodoPanel_module_css_default.chevron,
22923
23265
  "aria-hidden": true,
22924
- children: collapsed ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronUpOutline14, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutline14, {})
23266
+ children: collapsed ? (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronUpOutlineRegular, {}) : (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconChevronDownOutlineRegular, {})
22925
23267
  })
22926
23268
  ]
22927
23269
  }), !collapsed && (0, react_jsx_runtime.jsx)("ul", {
@@ -22964,6 +23306,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
22964
23306
  };
22965
23307
  //#endregion
22966
23308
  //#region lib/types/client/apply.js
23309
+ /** The shell-installed bridge, when this document runs inside the Desktop application. */
23310
+ function hostPathBridge() {
23311
+ return globalThis.__QILIN_HOST_PATHS__;
23312
+ }
22967
23313
  /** Services required by the Conversation plugin. */
22968
23314
  const inject = [
22969
23315
  "slots",
@@ -23152,6 +23498,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23152
23498
  activateView(sessionId, readConversationViewPreference(sessionId));
23153
23499
  };
23154
23500
  const conversationViews = (0, _qilin_agent_client_store.createSnapshotStore)(viewTabs());
23501
+ const viewPins = createViewPins();
23502
+ const viewActions = {
23503
+ getSnapshot: () => slots.entriesOfSlot("conversation.session.header.views.actions").length > 0,
23504
+ subscribe: (listener) => slots.subscribe("conversation.session.header.views.actions", listener)
23505
+ };
23155
23506
  const bindings = /* @__PURE__ */ new Set();
23156
23507
  const trackedBindings = /* @__PURE__ */ new WeakSet();
23157
23508
  const trackBinding = (binding) => {
@@ -23188,7 +23539,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23188
23539
  scope.effect(() => commands.register({
23189
23540
  name: "file",
23190
23541
  label: () => t("input.file"),
23191
- icon: _qilin_agent_client_ui_primitives.IconPaperclipOutline16,
23542
+ icon: _qilin_agent_client_ui_primitives.IconPaperclipOutlineRegular,
23192
23543
  available: (session) => inputHub.canPickFiles(session.sessionId),
23193
23544
  ui: {
23194
23545
  kind: "action",
@@ -23339,11 +23690,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23339
23690
  "conversation.session.header.corner": {
23340
23691
  kind: "single",
23341
23692
  scope: "session"
23693
+ },
23694
+ "conversation.session.header.views.actions": {
23695
+ kind: "list",
23696
+ scope: "root"
23342
23697
  }
23343
23698
  },
23344
23699
  store: conversationStore,
23345
23700
  inject: (sessionId, actions) => ({
23346
- hooks: { conversationViews },
23701
+ hooks: {
23702
+ conversationViews,
23703
+ entryPins: viewPins.unpinned,
23704
+ entryActions: viewActions
23705
+ },
23706
+ setPinned: viewPins.setPinned,
23347
23707
  open: (id) => {
23348
23708
  workspaceNavigation.openSession(id);
23349
23709
  },
@@ -23404,6 +23764,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23404
23764
  toggleCommandMenu: void 0,
23405
23765
  stop: void 0,
23406
23766
  hooks: {
23767
+ stopShortcut,
23407
23768
  busyEnter: submissionPolicy.busyEnter,
23408
23769
  fileUploads: ABSENT_FILE_UPLOADS,
23409
23770
  notices: ABSENT_NOTICES,
@@ -23414,13 +23775,45 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23414
23775
  const conversation = concreteConversation(ctx);
23415
23776
  const shell = inputHub.shell(sessionId);
23416
23777
  const inputTriggers = inputHub.inputTriggers(sessionId);
23778
+ const bridge = hostPathBridge();
23417
23779
  return {
23418
23780
  keyboard: shell,
23419
- addFiles: (files) => {
23781
+ addFiles: (files, directories = /* @__PURE__ */ new Set()) => {
23420
23782
  if (sessions.binding(sessionId) === void 0) return t("file.sessionUnavailable");
23783
+ if (shell.snapshot.phase === "adjudicating" || shell.snapshot.phase === "submitting") return t("attachment.dropBlocked");
23784
+ const uploads = [];
23785
+ const references = [];
23786
+ const cwd = sessions.list.getSnapshot().byId[sessionId]?.cwd;
23787
+ for (const file of files) {
23788
+ const directory = directories.has(file);
23789
+ if (bridge === void 0 && directory) return t("attachment.directoryDesktopOnly");
23790
+ const path = bridge?.pathFor(file) ?? "";
23791
+ if (directory && path === "") return t("attachment.pathUnavailable");
23792
+ if (path === "" || !directory && isImageMediaType(file.type)) {
23793
+ uploads.push(file);
23794
+ continue;
23795
+ }
23796
+ const relative = relativizeToCwd(path, cwd);
23797
+ const mention = formatFileMention({
23798
+ path: directory ? `${relative}/` : relative,
23799
+ kind: "file"
23800
+ }, false);
23801
+ if (mention === void 0) return t("attachment.pathUnsupported");
23802
+ const label = workspaceTitleOf(path) || file.name;
23803
+ references.push({
23804
+ source: "reference",
23805
+ ref: mention,
23806
+ label: directory ? `${label}/` : label,
23807
+ appearance: directory ? "folder" : "file",
23808
+ clipboardText: mention
23809
+ });
23810
+ }
23421
23811
  try {
23422
- const drafts = conversation.createDrafts(sessionId, files);
23423
- if (!shell.addAttachments(drafts.map((draft) => draft.id))) conversation.releaseDraftAttachments(drafts);
23812
+ const drafts = conversation.createDrafts(sessionId, uploads);
23813
+ if (!shell.addFiles(references, drafts.map((draft) => draft.id))) {
23814
+ conversation.releaseDraftAttachments(drafts);
23815
+ return t("attachment.dropBlocked");
23816
+ }
23424
23817
  return null;
23425
23818
  } catch (error) {
23426
23819
  if (error instanceof UnsupportedImageMediaTypeError) return t("image.unsupportedType");
@@ -23452,6 +23845,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
23452
23845
  scopedConversation(sessions, sessionId).cancel().catch(() => {});
23453
23846
  },
23454
23847
  hooks: {
23848
+ stopShortcut,
23455
23849
  busyEnter: submissionPolicy.busyEnter,
23456
23850
  fileUploads: conversation.fileUploads,
23457
23851
  notices: shell.notices,