@tutti-os/agent-gui 0.0.44 → 0.0.45
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/dist/agent-conversation/index.js +5 -4
- package/dist/agent-conversation/index.js.map +1 -1
- package/dist/agent-message-center/index.js +17 -11
- package/dist/agent-message-center/index.js.map +1 -1
- package/dist/app/renderer/agentactivity.css +99 -54
- package/dist/{chunk-GMLK2EFU.js → chunk-62QOR3TC.js} +4 -97
- package/dist/chunk-62QOR3TC.js.map +1 -0
- package/dist/{chunk-5UD2YEBX.js → chunk-AMNXH4DJ.js} +47 -14
- package/dist/{chunk-5UD2YEBX.js.map → chunk-AMNXH4DJ.js.map} +1 -1
- package/dist/{chunk-25VZHG6G.js → chunk-CZ7PS3DU.js} +4 -4
- package/dist/{chunk-ZORA4UAT.js → chunk-D6IYEVDT.js} +2 -2
- package/dist/chunk-EIC7XS3C.js +71 -0
- package/dist/chunk-EIC7XS3C.js.map +1 -0
- package/dist/chunk-FJG2EH4V.js +317 -0
- package/dist/chunk-FJG2EH4V.js.map +1 -0
- package/dist/{chunk-J4MU53PH.js → chunk-NZ2BGOJU.js} +2 -2
- package/dist/chunk-OL54R6OL.js +99 -0
- package/dist/chunk-OL54R6OL.js.map +1 -0
- package/dist/{chunk-ZTQKIJ5J.js → chunk-QT45WUPQ.js} +71 -20
- package/dist/chunk-QT45WUPQ.js.map +1 -0
- package/dist/{chunk-SF2PE7M6.js → chunk-UGV6JTWM.js} +4 -4
- package/dist/{chunk-IGXC7NRW.js → chunk-VFQR7AZI.js} +10 -63
- package/dist/chunk-VFQR7AZI.js.map +1 -0
- package/dist/{chunk-64OSXJRE.js → chunk-ZG3WZSMV.js} +2 -2
- package/dist/context-mention-palette/index.js +7 -6
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +157 -232
- package/dist/index.js.map +1 -1
- package/dist/uiSettings-BQS9r2eo.d.ts +6 -0
- package/dist/workbench/contribution.js +1 -1
- package/dist/workbench/index.d.ts +3 -0
- package/dist/workbench/index.js +13 -2
- package/dist/workbench/sessionTitle.d.ts +28 -0
- package/dist/workbench/sessionTitle.js +14 -0
- package/dist/workbench/sessionTitle.js.map +1 -0
- package/dist/workspace-agent-generated-files.js +3 -2
- package/package.json +19 -12
- package/dist/chunk-GMLK2EFU.js.map +0 -1
- package/dist/chunk-IGXC7NRW.js.map +0 -1
- package/dist/chunk-ZTQKIJ5J.js.map +0 -1
- /package/dist/{chunk-25VZHG6G.js.map → chunk-CZ7PS3DU.js.map} +0 -0
- /package/dist/{chunk-ZORA4UAT.js.map → chunk-D6IYEVDT.js.map} +0 -0
- /package/dist/{chunk-J4MU53PH.js.map → chunk-NZ2BGOJU.js.map} +0 -0
- /package/dist/{chunk-SF2PE7M6.js.map → chunk-UGV6JTWM.js.map} +0 -0
- /package/dist/{chunk-64OSXJRE.js.map → chunk-ZG3WZSMV.js.map} +0 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeAgentTitleText
|
|
3
|
+
} from "./chunk-GCBDIQDX.js";
|
|
4
|
+
import {
|
|
5
|
+
translateInUiLanguage
|
|
6
|
+
} from "./chunk-VFQR7AZI.js";
|
|
7
|
+
|
|
8
|
+
// shared/utils/agentSessionMentionText.ts
|
|
9
|
+
import {
|
|
10
|
+
isRichTextMentionHref,
|
|
11
|
+
parseRichTextMentionHref
|
|
12
|
+
} from "@tutti-os/ui-rich-text/core";
|
|
13
|
+
var MARKDOWN_LINK_PATTERN = /\[((?:\\.|[^\]\\])*)\]\(([^)\s]+)\)/g;
|
|
14
|
+
var MARKDOWN_LABEL_ESCAPE_PATTERN = /\\([\\[\]()])/g;
|
|
15
|
+
var SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE = {
|
|
16
|
+
"zh-CN": "@\u4F1A\u8BDD \xB7 ",
|
|
17
|
+
en: "@session \xB7 "
|
|
18
|
+
};
|
|
19
|
+
var PLAIN_SESSION_AGENT_LABELS = [
|
|
20
|
+
"Claude Code",
|
|
21
|
+
"Gemini CLI",
|
|
22
|
+
"Hermes Agent",
|
|
23
|
+
"OpenClaw",
|
|
24
|
+
"Nexight",
|
|
25
|
+
"Gemini",
|
|
26
|
+
"Hermes",
|
|
27
|
+
"Codex"
|
|
28
|
+
];
|
|
29
|
+
function formatAgentSessionMentionText(value, options = {}) {
|
|
30
|
+
const trimmed = value?.trim() ?? "";
|
|
31
|
+
if (!trimmed) {
|
|
32
|
+
return "";
|
|
33
|
+
}
|
|
34
|
+
const sessionMentionDisplayPrefix = sessionMentionDisplayPrefixForLanguage(
|
|
35
|
+
options.language
|
|
36
|
+
);
|
|
37
|
+
const withSessionMentionsNormalized = trimmed.replace(
|
|
38
|
+
MARKDOWN_LINK_PATTERN,
|
|
39
|
+
(fullMatch, rawLabel, href) => {
|
|
40
|
+
const label = unescapeMarkdownLabel(rawLabel);
|
|
41
|
+
const mention = parseRichTextMentionHref(href, label);
|
|
42
|
+
if (!mention) {
|
|
43
|
+
return isRichTextMentionHref(href) ? label : fullMatch;
|
|
44
|
+
}
|
|
45
|
+
const providerId = mention.providerId.trim().toLowerCase();
|
|
46
|
+
const displayLabel = label || mention.label;
|
|
47
|
+
if (providerId === "agent-session") {
|
|
48
|
+
return formatSessionLabel(displayLabel, sessionMentionDisplayPrefix);
|
|
49
|
+
}
|
|
50
|
+
if (providerId === "workspace-issue") {
|
|
51
|
+
return formatIssueLabel(displayLabel);
|
|
52
|
+
}
|
|
53
|
+
return displayLabel;
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
const normalized = normalizeAgentTitleText(withSessionMentionsNormalized);
|
|
57
|
+
if (isPlainSessionMentionText(normalized, sessionMentionDisplayPrefix)) {
|
|
58
|
+
return formatSessionLabel(normalized, sessionMentionDisplayPrefix);
|
|
59
|
+
}
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
function isPlainSessionMentionText(value, sessionMentionDisplayPrefix) {
|
|
63
|
+
const trimmed = value.trim();
|
|
64
|
+
if (!trimmed.startsWith("@") || trimmed.startsWith(sessionMentionDisplayPrefix)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return PLAIN_SESSION_AGENT_LABELS.some((agentLabel) => {
|
|
68
|
+
const ampersandSeparator = ` & ${agentLabel}`;
|
|
69
|
+
const ampersandIndex = trimmed.indexOf(ampersandSeparator);
|
|
70
|
+
if (ampersandIndex > 1) {
|
|
71
|
+
const trailing = trimmed.slice(
|
|
72
|
+
ampersandIndex + ampersandSeparator.length
|
|
73
|
+
);
|
|
74
|
+
if (trailing === "" || trailing.startsWith(" ")) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const dottedSeparator = ` \xB7 ${agentLabel} \xB7 `;
|
|
79
|
+
return trimmed.indexOf(dottedSeparator) > 1;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function sessionMentionDisplayPrefixForLanguage(language) {
|
|
83
|
+
return SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE[language ?? "en"];
|
|
84
|
+
}
|
|
85
|
+
function formatSessionLabel(label, sessionMentionDisplayPrefix) {
|
|
86
|
+
const normalizedLabel = label.trim().replace(/^@+/, "").trim();
|
|
87
|
+
return normalizedLabel ? `${sessionMentionDisplayPrefix}${normalizedLabel}` : label.trim();
|
|
88
|
+
}
|
|
89
|
+
function formatIssueLabel(label) {
|
|
90
|
+
const normalizedLabel = label.trim().replace(/^@+/, "").trim();
|
|
91
|
+
return normalizedLabel ? `@Task \xB7 ${normalizedLabel}` : label.trim();
|
|
92
|
+
}
|
|
93
|
+
function unescapeMarkdownLabel(label) {
|
|
94
|
+
return label.replace(MARKDOWN_LABEL_ESCAPE_PATTERN, "$1");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// contexts/settings/domain/agentSettings.providerMeta.ts
|
|
98
|
+
var AGENT_PROVIDER_LABEL = {
|
|
99
|
+
"claude-code": "Claude Code",
|
|
100
|
+
codex: "Codex",
|
|
101
|
+
nexight: "Nexight",
|
|
102
|
+
opencode: "OpenCode",
|
|
103
|
+
gemini: "Gemini CLI",
|
|
104
|
+
openclaw: "OpenClaw",
|
|
105
|
+
hermes: "Hermes Agent"
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// shared/agentConversationTitleProjection.ts
|
|
109
|
+
function normalizeAgentGUIProviderIdentity(provider) {
|
|
110
|
+
switch (provider?.trim().toLowerCase() ?? "") {
|
|
111
|
+
case "claude-code":
|
|
112
|
+
case "claude":
|
|
113
|
+
case "claude code":
|
|
114
|
+
return "claude-code";
|
|
115
|
+
case "codex":
|
|
116
|
+
return "codex";
|
|
117
|
+
case "nexight":
|
|
118
|
+
case "tutti":
|
|
119
|
+
return "nexight";
|
|
120
|
+
case "gemini":
|
|
121
|
+
return "gemini";
|
|
122
|
+
case "hermes":
|
|
123
|
+
return "hermes";
|
|
124
|
+
case "openclaw":
|
|
125
|
+
return "openclaw";
|
|
126
|
+
default:
|
|
127
|
+
return "unknown";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function resolveAgentGUIProviderIdentity(input) {
|
|
131
|
+
const candidates = [
|
|
132
|
+
input.sessionProvider,
|
|
133
|
+
input.workspaceSessionProvider,
|
|
134
|
+
input.conversationProvider,
|
|
135
|
+
timelineProviderHint(input.timelineItems ?? [])
|
|
136
|
+
];
|
|
137
|
+
for (const candidate of candidates) {
|
|
138
|
+
const normalized = normalizeAgentGUIProviderIdentity(candidate);
|
|
139
|
+
if (normalized !== "unknown") {
|
|
140
|
+
return normalized;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return "unknown";
|
|
144
|
+
}
|
|
145
|
+
function resolveAgentGUIConversationTitle(title, provider) {
|
|
146
|
+
const normalizedTitle = stripAgentGUITitleTrailingPeriod(
|
|
147
|
+
normalizeAgentTitleText(title)
|
|
148
|
+
);
|
|
149
|
+
if (normalizedTitle) {
|
|
150
|
+
return {
|
|
151
|
+
title: normalizedTitle,
|
|
152
|
+
titleFallback: null
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (provider === "unknown") {
|
|
156
|
+
return {
|
|
157
|
+
title: "",
|
|
158
|
+
titleFallback: "generic-agent"
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
title: AGENT_PROVIDER_LABEL[provider],
|
|
163
|
+
titleFallback: null
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function resolveAgentGUIConversationDisplayTitle(input, fallbackAgentLabel) {
|
|
167
|
+
if (input.title) {
|
|
168
|
+
return stripAgentGUITitleTrailingPeriod(
|
|
169
|
+
normalizeAgentTitleText(input.title)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (input.titleFallback === "generic-agent") {
|
|
173
|
+
return stripAgentGUITitleTrailingPeriod(fallbackAgentLabel);
|
|
174
|
+
}
|
|
175
|
+
return "";
|
|
176
|
+
}
|
|
177
|
+
function formatAgentGUIConversationPlainTitle(input, options = {}) {
|
|
178
|
+
return formatAgentSessionMentionText(
|
|
179
|
+
resolveAgentGUIConversationDisplayTitle(
|
|
180
|
+
input,
|
|
181
|
+
options.fallbackAgentLabel ?? "Agent"
|
|
182
|
+
),
|
|
183
|
+
{
|
|
184
|
+
language: options.language
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
function resolveAgentGUIDockConversationTitle(input) {
|
|
189
|
+
return resolveAgentGUIExplicitConversationTitle(input);
|
|
190
|
+
}
|
|
191
|
+
function resolveAgentGUIExplicitConversationTitle(input) {
|
|
192
|
+
if (input.titleFallback) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const title = stripAgentGUITitleTrailingPeriod(
|
|
196
|
+
normalizeAgentTitleText(input.title)
|
|
197
|
+
);
|
|
198
|
+
if (!title) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
if (isAgentGUIUntitledTaskTitle(title)) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if (input.provider !== "unknown" && title === AGENT_PROVIDER_LABEL[input.provider]) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
return title;
|
|
208
|
+
}
|
|
209
|
+
function resolveAgentGUIProviderDisplayLabel(provider, fallbackAgentLabel) {
|
|
210
|
+
const resolvedProvider = normalizeAgentGUIProviderIdentity(provider);
|
|
211
|
+
if (resolvedProvider === "unknown") {
|
|
212
|
+
return fallbackAgentLabel;
|
|
213
|
+
}
|
|
214
|
+
return AGENT_PROVIDER_LABEL[resolvedProvider];
|
|
215
|
+
}
|
|
216
|
+
function firstAgentGUIUserMessageTitle(messages) {
|
|
217
|
+
const userMessage = [...messages].filter(
|
|
218
|
+
(message) => messageRole(message) === "user" && messageText(message).length > 0
|
|
219
|
+
).sort(compareMessagesAscending)[0];
|
|
220
|
+
return userMessage ? messageText(userMessage) : "";
|
|
221
|
+
}
|
|
222
|
+
function messageRole(message) {
|
|
223
|
+
const role = message.role?.trim().toLowerCase();
|
|
224
|
+
if (role === "user") {
|
|
225
|
+
return "user";
|
|
226
|
+
}
|
|
227
|
+
if (role === "assistant" || role === "agent") {
|
|
228
|
+
return "agent";
|
|
229
|
+
}
|
|
230
|
+
const kind = message.kind?.trim().toLowerCase() ?? "";
|
|
231
|
+
if (kind === "message.user") {
|
|
232
|
+
return "user";
|
|
233
|
+
}
|
|
234
|
+
if (kind === "message.assistant" || kind === "message.agent") {
|
|
235
|
+
return "agent";
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
function messageText(message) {
|
|
240
|
+
const payload = message.payload;
|
|
241
|
+
const displayPrompt = typeof payload?.displayPrompt === "string" ? payload.displayPrompt : "";
|
|
242
|
+
const text = typeof payload?.text === "string" ? payload.text : "";
|
|
243
|
+
const content = typeof payload?.content === "string" ? payload.content : "";
|
|
244
|
+
return normalizeAgentTitleText(displayPrompt || text || content);
|
|
245
|
+
}
|
|
246
|
+
function compareMessagesAscending(left, right) {
|
|
247
|
+
const leftTime = left.occurredAtUnixMs ?? left.completedAtUnixMs ?? left.startedAtUnixMs ?? 0;
|
|
248
|
+
const rightTime = right.occurredAtUnixMs ?? right.completedAtUnixMs ?? right.startedAtUnixMs ?? 0;
|
|
249
|
+
const timeDiff = leftTime - rightTime;
|
|
250
|
+
if (timeDiff !== 0) {
|
|
251
|
+
return timeDiff;
|
|
252
|
+
}
|
|
253
|
+
const sequenceDiff = messageSequence(left) - messageSequence(right) || (left.messageId ?? "").localeCompare(right.messageId ?? "");
|
|
254
|
+
return sequenceDiff;
|
|
255
|
+
}
|
|
256
|
+
function messageSequence(message) {
|
|
257
|
+
const numericId = typeof message.id === "number" && Number.isFinite(message.id) ? message.id : 0;
|
|
258
|
+
return message.version ?? numericId;
|
|
259
|
+
}
|
|
260
|
+
function stripAgentGUITitleTrailingPeriod(title) {
|
|
261
|
+
return title.trimEnd().replace(/[.。]+$/u, "").trimEnd();
|
|
262
|
+
}
|
|
263
|
+
function isAgentGUIUntitledTaskTitle(title) {
|
|
264
|
+
return localizedAgentGUIUntitledTaskLabels().has(compactTitleText(title));
|
|
265
|
+
}
|
|
266
|
+
function localizedAgentGUIUntitledTaskLabels() {
|
|
267
|
+
return new Set(
|
|
268
|
+
["en", "zh-CN"].map(
|
|
269
|
+
(language) => compactTitleText(
|
|
270
|
+
translateInUiLanguage(
|
|
271
|
+
language,
|
|
272
|
+
"agentHost.workspaceAgentsUntitledTask"
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
).filter(Boolean)
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
function timelineProviderHint(timelineItems) {
|
|
279
|
+
for (const item of timelineItems) {
|
|
280
|
+
if (isUserTimelineItem(item)) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const normalized = normalizeAgentGUIProviderIdentity(item.actorId);
|
|
284
|
+
if (normalized !== "unknown") {
|
|
285
|
+
return normalized;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
function isUserTimelineItem(item) {
|
|
291
|
+
const role = item.role?.trim().toLowerCase();
|
|
292
|
+
if (role === "user") {
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
const actorType = item.actorType.trim().toLowerCase();
|
|
296
|
+
if (actorType === "user") {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
return item.itemType.trim().toLowerCase() === "message.user";
|
|
300
|
+
}
|
|
301
|
+
function compactTitleText(value) {
|
|
302
|
+
return value.trim().replace(/\s+/g, " ");
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export {
|
|
306
|
+
AGENT_PROVIDER_LABEL,
|
|
307
|
+
formatAgentSessionMentionText,
|
|
308
|
+
normalizeAgentGUIProviderIdentity,
|
|
309
|
+
resolveAgentGUIProviderIdentity,
|
|
310
|
+
resolveAgentGUIConversationTitle,
|
|
311
|
+
formatAgentGUIConversationPlainTitle,
|
|
312
|
+
resolveAgentGUIDockConversationTitle,
|
|
313
|
+
resolveAgentGUIExplicitConversationTitle,
|
|
314
|
+
resolveAgentGUIProviderDisplayLabel,
|
|
315
|
+
firstAgentGUIUserMessageTitle
|
|
316
|
+
};
|
|
317
|
+
//# sourceMappingURL=chunk-FJG2EH4V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../shared/utils/agentSessionMentionText.ts","../contexts/settings/domain/agentSettings.providerMeta.ts","../shared/agentConversationTitleProjection.ts"],"sourcesContent":["import type { UiLanguage } from \"../../contexts/settings/domain/agentSettings\";\nimport { normalizeAgentTitleText } from \"./agentTitleText.ts\";\nimport {\n isRichTextMentionHref,\n parseRichTextMentionHref\n} from \"@tutti-os/ui-rich-text/core\";\n\nconst MARKDOWN_LINK_PATTERN = /\\[((?:\\\\.|[^\\]\\\\])*)\\]\\(([^)\\s]+)\\)/g;\nconst MARKDOWN_LABEL_ESCAPE_PATTERN = /\\\\([\\\\[\\]()])/g;\nconst SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE: Record<UiLanguage, string> = {\n \"zh-CN\": \"@会话 · \",\n en: \"@session · \"\n};\nconst PLAIN_SESSION_AGENT_LABELS = [\n \"Claude Code\",\n \"Gemini CLI\",\n \"Hermes Agent\",\n \"OpenClaw\",\n \"Nexight\",\n \"Gemini\",\n \"Hermes\",\n \"Codex\"\n] as const;\n\nexport interface FormatAgentSessionMentionTextOptions {\n language?: UiLanguage;\n}\n\nexport function formatAgentSessionMentionText(\n value: string | null | undefined,\n options: FormatAgentSessionMentionTextOptions = {}\n): string {\n const trimmed = value?.trim() ?? \"\";\n if (!trimmed) {\n return \"\";\n }\n const sessionMentionDisplayPrefix = sessionMentionDisplayPrefixForLanguage(\n options.language\n );\n\n const withSessionMentionsNormalized = trimmed.replace(\n MARKDOWN_LINK_PATTERN,\n (fullMatch, rawLabel: string, href: string) => {\n const label = unescapeMarkdownLabel(rawLabel);\n const mention = parseRichTextMentionHref(href, label);\n if (!mention) {\n return isRichTextMentionHref(href) ? label : fullMatch;\n }\n const providerId = mention.providerId.trim().toLowerCase();\n const displayLabel = label || mention.label;\n if (providerId === \"agent-session\") {\n return formatSessionLabel(displayLabel, sessionMentionDisplayPrefix);\n }\n if (providerId === \"workspace-issue\") {\n return formatIssueLabel(displayLabel);\n }\n return displayLabel;\n }\n );\n const normalized = normalizeAgentTitleText(withSessionMentionsNormalized);\n if (isPlainSessionMentionText(normalized, sessionMentionDisplayPrefix)) {\n return formatSessionLabel(normalized, sessionMentionDisplayPrefix);\n }\n return normalized;\n}\n\nfunction isPlainSessionMentionText(\n value: string,\n sessionMentionDisplayPrefix: string\n): boolean {\n const trimmed = value.trim();\n if (\n !trimmed.startsWith(\"@\") ||\n trimmed.startsWith(sessionMentionDisplayPrefix)\n ) {\n return false;\n }\n\n return PLAIN_SESSION_AGENT_LABELS.some((agentLabel) => {\n const ampersandSeparator = ` & ${agentLabel}`;\n const ampersandIndex = trimmed.indexOf(ampersandSeparator);\n if (ampersandIndex > 1) {\n const trailing = trimmed.slice(\n ampersandIndex + ampersandSeparator.length\n );\n if (trailing === \"\" || trailing.startsWith(\" \")) {\n return true;\n }\n }\n\n const dottedSeparator = ` · ${agentLabel} · `;\n return trimmed.indexOf(dottedSeparator) > 1;\n });\n}\n\nfunction sessionMentionDisplayPrefixForLanguage(\n language: UiLanguage | undefined\n): string {\n return SESSION_MENTION_DISPLAY_PREFIX_BY_LANGUAGE[language ?? \"en\"];\n}\n\nfunction formatSessionLabel(\n label: string,\n sessionMentionDisplayPrefix: string\n): string {\n const normalizedLabel = label.trim().replace(/^@+/, \"\").trim();\n return normalizedLabel\n ? `${sessionMentionDisplayPrefix}${normalizedLabel}`\n : label.trim();\n}\n\nfunction formatIssueLabel(label: string): string {\n const normalizedLabel = label.trim().replace(/^@+/, \"\").trim();\n return normalizedLabel ? `@Task · ${normalizedLabel}` : label.trim();\n}\n\nfunction unescapeMarkdownLabel(label: string): string {\n return label.replace(MARKDOWN_LABEL_ESCAPE_PATTERN, \"$1\");\n}\n","import type { AgentProvider } from \"./agentSettings\";\n\nexport const AGENT_PROVIDER_LABEL: Record<AgentProvider, string> = {\n \"claude-code\": \"Claude Code\",\n codex: \"Codex\",\n nexight: \"Nexight\",\n opencode: \"OpenCode\",\n gemini: \"Gemini CLI\",\n openclaw: \"OpenClaw\",\n hermes: \"Hermes Agent\"\n};\n\nexport interface AgentProviderCapabilities {\n runtimeObservation: \"jsonl\" | \"provider-api\" | \"none\";\n experimental: boolean;\n}\n\nexport const AGENT_PROVIDER_CAPABILITIES: Record<\n AgentProvider,\n AgentProviderCapabilities\n> = {\n \"claude-code\": {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n codex: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n nexight: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n opencode: {\n runtimeObservation: \"provider-api\",\n experimental: false\n },\n gemini: {\n runtimeObservation: \"none\",\n experimental: false\n },\n openclaw: {\n runtimeObservation: \"jsonl\",\n experimental: false\n },\n hermes: {\n runtimeObservation: \"jsonl\",\n experimental: false\n }\n};\n","import { AGENT_PROVIDER_LABEL } from \"../contexts/settings/domain/agentSettings.providerMeta.ts\";\nimport type { UiLanguage } from \"../contexts/settings/domain/agentSettings.ts\";\nimport { translateInUiLanguage } from \"../i18n/runtime.ts\";\nimport type { AgentGUIProvider } from \"../types.ts\";\nimport type { WorkspaceAgentActivityTimelineItem } from \"./workspaceAgentActivityTypes.ts\";\nimport { formatAgentSessionMentionText } from \"./utils/agentSessionMentionText.ts\";\nimport { normalizeAgentTitleText } from \"./utils/agentTitleText.ts\";\n\nexport type AgentGUIResolvedProvider = AgentGUIProvider | \"unknown\";\nexport type AgentGUIConversationTitleFallback = \"generic-agent\" | null;\n\nexport interface AgentGUIConversationPlainTitleOptions {\n fallbackAgentLabel?: string;\n language?: UiLanguage;\n}\n\nexport interface AgentGUIConversationTitleMessage {\n id?: number | string | null;\n messageId?: string | null;\n version?: number | null;\n role?: string | null;\n kind?: string | null;\n payload?: {\n content?: unknown;\n displayPrompt?: unknown;\n text?: unknown;\n } | null;\n occurredAtUnixMs?: number | null;\n completedAtUnixMs?: number | null;\n startedAtUnixMs?: number | null;\n}\n\nexport function normalizeAgentGUIProviderIdentity(\n provider: string | null | undefined\n): AgentGUIResolvedProvider {\n switch (provider?.trim().toLowerCase() ?? \"\") {\n case \"claude-code\":\n case \"claude\":\n case \"claude code\":\n return \"claude-code\";\n case \"codex\":\n return \"codex\";\n case \"nexight\":\n case \"tutti\":\n return \"nexight\";\n case \"gemini\":\n return \"gemini\";\n case \"hermes\":\n return \"hermes\";\n case \"openclaw\":\n return \"openclaw\";\n default:\n return \"unknown\";\n }\n}\n\nexport function resolveAgentGUIProviderIdentity(input: {\n sessionProvider?: string | null;\n workspaceSessionProvider?: string | null;\n conversationProvider?: string | null;\n timelineItems?: readonly WorkspaceAgentActivityTimelineItem[];\n}): AgentGUIResolvedProvider {\n const candidates = [\n input.sessionProvider,\n input.workspaceSessionProvider,\n input.conversationProvider,\n timelineProviderHint(input.timelineItems ?? [])\n ];\n for (const candidate of candidates) {\n const normalized = normalizeAgentGUIProviderIdentity(candidate);\n if (normalized !== \"unknown\") {\n return normalized;\n }\n }\n return \"unknown\";\n}\n\nexport function resolveAgentGUIConversationTitle(\n title: string | null | undefined,\n provider: AgentGUIResolvedProvider\n): {\n title: string;\n titleFallback: AgentGUIConversationTitleFallback;\n} {\n const normalizedTitle = stripAgentGUITitleTrailingPeriod(\n normalizeAgentTitleText(title)\n );\n if (normalizedTitle) {\n return {\n title: normalizedTitle,\n titleFallback: null\n };\n }\n if (provider === \"unknown\") {\n return {\n title: \"\",\n titleFallback: \"generic-agent\"\n };\n }\n return {\n title: AGENT_PROVIDER_LABEL[provider],\n titleFallback: null\n };\n}\n\nexport function resolveAgentGUIConversationDisplayTitle(\n input: {\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n },\n fallbackAgentLabel: string\n): string {\n if (input.title) {\n return stripAgentGUITitleTrailingPeriod(\n normalizeAgentTitleText(input.title)\n );\n }\n if (input.titleFallback === \"generic-agent\") {\n return stripAgentGUITitleTrailingPeriod(fallbackAgentLabel);\n }\n return \"\";\n}\n\nexport function formatAgentGUIConversationPlainTitle(\n input: {\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n },\n options: AgentGUIConversationPlainTitleOptions = {}\n): string {\n return formatAgentSessionMentionText(\n resolveAgentGUIConversationDisplayTitle(\n input,\n options.fallbackAgentLabel ?? \"Agent\"\n ),\n {\n language: options.language\n }\n );\n}\n\nexport function resolveAgentGUIDockConversationTitle(input: {\n provider: AgentGUIResolvedProvider;\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n}): string | null {\n return resolveAgentGUIExplicitConversationTitle(input);\n}\n\nexport function resolveAgentGUIExplicitConversationTitle(input: {\n provider: AgentGUIResolvedProvider;\n title: string;\n titleFallback?: AgentGUIConversationTitleFallback;\n}): string | null {\n if (input.titleFallback) {\n return null;\n }\n\n const title = stripAgentGUITitleTrailingPeriod(\n normalizeAgentTitleText(input.title)\n );\n if (!title) {\n return null;\n }\n if (isAgentGUIUntitledTaskTitle(title)) {\n return null;\n }\n\n if (\n input.provider !== \"unknown\" &&\n title === AGENT_PROVIDER_LABEL[input.provider]\n ) {\n return null;\n }\n\n return title;\n}\n\nexport function resolveAgentGUIProviderDisplayLabel(\n provider: string | null | undefined,\n fallbackAgentLabel: string\n): string {\n const resolvedProvider = normalizeAgentGUIProviderIdentity(provider);\n if (resolvedProvider === \"unknown\") {\n return fallbackAgentLabel;\n }\n return AGENT_PROVIDER_LABEL[resolvedProvider];\n}\n\nexport function firstAgentGUIUserMessageTitle(\n messages: readonly AgentGUIConversationTitleMessage[]\n): string {\n const userMessage = [...messages]\n .filter(\n (message) =>\n messageRole(message) === \"user\" && messageText(message).length > 0\n )\n .sort(compareMessagesAscending)[0];\n return userMessage ? messageText(userMessage) : \"\";\n}\n\nfunction messageRole(\n message: AgentGUIConversationTitleMessage\n): \"user\" | \"agent\" | null {\n const role = message.role?.trim().toLowerCase();\n if (role === \"user\") {\n return \"user\";\n }\n if (role === \"assistant\" || role === \"agent\") {\n return \"agent\";\n }\n const kind = message.kind?.trim().toLowerCase() ?? \"\";\n if (kind === \"message.user\") {\n return \"user\";\n }\n if (kind === \"message.assistant\" || kind === \"message.agent\") {\n return \"agent\";\n }\n return null;\n}\n\nfunction messageText(message: AgentGUIConversationTitleMessage): string {\n const payload = message.payload;\n const displayPrompt =\n typeof payload?.displayPrompt === \"string\" ? payload.displayPrompt : \"\";\n const text = typeof payload?.text === \"string\" ? payload.text : \"\";\n const content = typeof payload?.content === \"string\" ? payload.content : \"\";\n return normalizeAgentTitleText(displayPrompt || text || content);\n}\n\nfunction compareMessagesAscending(\n left: AgentGUIConversationTitleMessage,\n right: AgentGUIConversationTitleMessage\n): number {\n const leftTime =\n left.occurredAtUnixMs ??\n left.completedAtUnixMs ??\n left.startedAtUnixMs ??\n 0;\n const rightTime =\n right.occurredAtUnixMs ??\n right.completedAtUnixMs ??\n right.startedAtUnixMs ??\n 0;\n const timeDiff = leftTime - rightTime;\n if (timeDiff !== 0) {\n return timeDiff;\n }\n const sequenceDiff =\n messageSequence(left) - messageSequence(right) ||\n (left.messageId ?? \"\").localeCompare(right.messageId ?? \"\");\n return sequenceDiff;\n}\n\nfunction messageSequence(message: AgentGUIConversationTitleMessage): number {\n const numericId =\n typeof message.id === \"number\" && Number.isFinite(message.id)\n ? message.id\n : 0;\n return message.version ?? numericId;\n}\n\nfunction stripAgentGUITitleTrailingPeriod(title: string): string {\n return title\n .trimEnd()\n .replace(/[.。]+$/u, \"\")\n .trimEnd();\n}\n\nfunction isAgentGUIUntitledTaskTitle(title: string): boolean {\n return localizedAgentGUIUntitledTaskLabels().has(compactTitleText(title));\n}\n\nfunction localizedAgentGUIUntitledTaskLabels(): Set<string> {\n return new Set(\n ([\"en\", \"zh-CN\"] as const)\n .map((language) =>\n compactTitleText(\n translateInUiLanguage(\n language,\n \"agentHost.workspaceAgentsUntitledTask\"\n )\n )\n )\n .filter(Boolean)\n );\n}\n\nfunction timelineProviderHint(\n timelineItems: readonly WorkspaceAgentActivityTimelineItem[]\n): string | null {\n for (const item of timelineItems) {\n if (isUserTimelineItem(item)) {\n continue;\n }\n const normalized = normalizeAgentGUIProviderIdentity(item.actorId);\n if (normalized !== \"unknown\") {\n return normalized;\n }\n }\n return null;\n}\n\nfunction isUserTimelineItem(item: WorkspaceAgentActivityTimelineItem): boolean {\n const role = item.role?.trim().toLowerCase();\n if (role === \"user\") {\n return true;\n }\n const actorType = item.actorType.trim().toLowerCase();\n if (actorType === \"user\") {\n return true;\n }\n return item.itemType.trim().toLowerCase() === \"message.user\";\n}\n\nfunction compactTitleText(value: string): string {\n return value.trim().replace(/\\s+/g, \" \");\n}\n"],"mappings":"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","names":[]}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "./chunk-MTFSQWZ6.js";
|
|
15
15
|
import {
|
|
16
16
|
translate
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-EIC7XS3C.js";
|
|
18
18
|
|
|
19
19
|
// shared/managedAgentProviders.ts
|
|
20
20
|
function normalizeManagedAgentProvider(provider) {
|
|
@@ -113,4 +113,4 @@ export {
|
|
|
113
113
|
userAvatarPlaceholderUrl,
|
|
114
114
|
workspaceAgentActivityStatusLabel
|
|
115
115
|
};
|
|
116
|
-
//# sourceMappingURL=chunk-
|
|
116
|
+
//# sourceMappingURL=chunk-NZ2BGOJU.js.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
firstAgentGUIUserMessageTitle,
|
|
3
|
+
formatAgentGUIConversationPlainTitle,
|
|
4
|
+
formatAgentSessionMentionText,
|
|
5
|
+
normalizeAgentGUIProviderIdentity,
|
|
6
|
+
resolveAgentGUIExplicitConversationTitle
|
|
7
|
+
} from "./chunk-FJG2EH4V.js";
|
|
8
|
+
|
|
9
|
+
// workbench/sessionTitle.ts
|
|
10
|
+
function formatAgentGuiSessionPlainTitle(title, options = {}) {
|
|
11
|
+
return formatAgentSessionMentionText(title, { language: options.language });
|
|
12
|
+
}
|
|
13
|
+
function formatAgentGuiConversationPlainTitle(conversation, options = {}) {
|
|
14
|
+
return formatAgentGUIConversationPlainTitle(conversation, options);
|
|
15
|
+
}
|
|
16
|
+
function resolveAgentGuiWorkbenchSessionTitle({
|
|
17
|
+
agentSessionId,
|
|
18
|
+
fallbackTitle,
|
|
19
|
+
language,
|
|
20
|
+
provider,
|
|
21
|
+
snapshot
|
|
22
|
+
}) {
|
|
23
|
+
const normalizedAgentSessionId = agentSessionId?.trim() ?? "";
|
|
24
|
+
if (!normalizedAgentSessionId) {
|
|
25
|
+
return { agentSessionId: null, source: "none", title: null };
|
|
26
|
+
}
|
|
27
|
+
const session = snapshot.sessions.find(
|
|
28
|
+
(item) => item.agentSessionId === normalizedAgentSessionId
|
|
29
|
+
);
|
|
30
|
+
const sessionMessages = snapshot.sessionMessagesById[normalizedAgentSessionId] ?? [];
|
|
31
|
+
const normalizedProvider = normalizeAgentGUIProviderIdentity(
|
|
32
|
+
session?.provider ?? provider
|
|
33
|
+
);
|
|
34
|
+
const snapshotTitle = resolveDisplayableSnapshotSessionTitle({
|
|
35
|
+
messages: sessionMessages,
|
|
36
|
+
provider: normalizedProvider,
|
|
37
|
+
sessionTitle: session?.title ?? "",
|
|
38
|
+
language
|
|
39
|
+
});
|
|
40
|
+
if (snapshotTitle) {
|
|
41
|
+
return {
|
|
42
|
+
agentSessionId: normalizedAgentSessionId,
|
|
43
|
+
source: "snapshot",
|
|
44
|
+
title: snapshotTitle
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (session || sessionMessages.length > 0) {
|
|
48
|
+
return {
|
|
49
|
+
agentSessionId: normalizedAgentSessionId,
|
|
50
|
+
source: "none",
|
|
51
|
+
title: null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const fallbackDisplayTitle = formatAgentGuiConversationPlainTitle(
|
|
55
|
+
{ title: fallbackTitle ?? "", titleFallback: null },
|
|
56
|
+
{ language }
|
|
57
|
+
);
|
|
58
|
+
return fallbackDisplayTitle ? {
|
|
59
|
+
agentSessionId: normalizedAgentSessionId,
|
|
60
|
+
source: "fallback",
|
|
61
|
+
title: fallbackDisplayTitle
|
|
62
|
+
} : {
|
|
63
|
+
agentSessionId: normalizedAgentSessionId,
|
|
64
|
+
source: "none",
|
|
65
|
+
title: null
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function resolveDisplayableSnapshotSessionTitle(input) {
|
|
69
|
+
const explicitSessionTitle = explicitConversationTitle({
|
|
70
|
+
language: input.language,
|
|
71
|
+
provider: input.provider,
|
|
72
|
+
title: input.sessionTitle
|
|
73
|
+
});
|
|
74
|
+
if (explicitSessionTitle) {
|
|
75
|
+
return explicitSessionTitle;
|
|
76
|
+
}
|
|
77
|
+
return explicitConversationTitle({
|
|
78
|
+
language: input.language,
|
|
79
|
+
provider: input.provider,
|
|
80
|
+
title: firstAgentGUIUserMessageTitle(input.messages)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function explicitConversationTitle(input) {
|
|
84
|
+
return resolveAgentGUIExplicitConversationTitle({
|
|
85
|
+
provider: input.provider,
|
|
86
|
+
title: formatAgentGuiConversationPlainTitle(
|
|
87
|
+
{ title: input.title ?? "", titleFallback: null },
|
|
88
|
+
{ language: input.language }
|
|
89
|
+
),
|
|
90
|
+
titleFallback: null
|
|
91
|
+
}) ?? "";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
formatAgentGuiSessionPlainTitle,
|
|
96
|
+
formatAgentGuiConversationPlainTitle,
|
|
97
|
+
resolveAgentGuiWorkbenchSessionTitle
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=chunk-OL54R6OL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../workbench/sessionTitle.ts"],"sourcesContent":["import type {\n AgentActivityMessage,\n AgentActivitySnapshot\n} from \"@tutti-os/agent-activity-core\";\nimport type { UiLanguage } from \"../contexts/settings/domain/agentSettings\";\nimport {\n firstAgentGUIUserMessageTitle,\n formatAgentGUIConversationPlainTitle,\n normalizeAgentGUIProviderIdentity,\n resolveAgentGUIExplicitConversationTitle,\n type AgentGUIResolvedProvider\n} from \"../shared/agentConversationTitleProjection.ts\";\nimport { formatAgentSessionMentionText } from \"../shared/utils/agentSessionMentionText.ts\";\nimport type { AgentGuiWorkbenchProvider } from \"./types.ts\";\n\nexport interface AgentGuiSessionTitleFormatOptions {\n fallbackAgentLabel?: string;\n language?: UiLanguage;\n}\n\nexport interface ResolveAgentGuiWorkbenchSessionTitleInput extends AgentGuiSessionTitleFormatOptions {\n agentSessionId?: string | null;\n fallbackTitle?: string | null;\n provider: AgentGuiWorkbenchProvider | string;\n snapshot: AgentActivitySnapshot;\n}\n\nexport interface AgentGuiWorkbenchSessionTitleResult {\n agentSessionId: string | null;\n source: \"snapshot\" | \"fallback\" | \"none\";\n title: string | null;\n}\n\nexport function formatAgentGuiSessionPlainTitle(\n title: string | null | undefined,\n options: AgentGuiSessionTitleFormatOptions = {}\n): string {\n return formatAgentSessionMentionText(title, { language: options.language });\n}\n\nexport function formatAgentGuiConversationPlainTitle(\n conversation: {\n title: string;\n titleFallback?: \"generic-agent\" | null;\n },\n options: AgentGuiSessionTitleFormatOptions = {}\n): string {\n return formatAgentGUIConversationPlainTitle(conversation, options);\n}\n\nexport function resolveAgentGuiWorkbenchSessionTitle({\n agentSessionId,\n fallbackTitle,\n language,\n provider,\n snapshot\n}: ResolveAgentGuiWorkbenchSessionTitleInput): AgentGuiWorkbenchSessionTitleResult {\n const normalizedAgentSessionId = agentSessionId?.trim() ?? \"\";\n if (!normalizedAgentSessionId) {\n return { agentSessionId: null, source: \"none\", title: null };\n }\n\n const session = snapshot.sessions.find(\n (item) => item.agentSessionId === normalizedAgentSessionId\n );\n const sessionMessages =\n snapshot.sessionMessagesById[normalizedAgentSessionId] ?? [];\n const normalizedProvider = normalizeAgentGUIProviderIdentity(\n session?.provider ?? provider\n );\n const snapshotTitle = resolveDisplayableSnapshotSessionTitle({\n messages: sessionMessages,\n provider: normalizedProvider,\n sessionTitle: session?.title ?? \"\",\n language\n });\n if (snapshotTitle) {\n return {\n agentSessionId: normalizedAgentSessionId,\n source: \"snapshot\",\n title: snapshotTitle\n };\n }\n\n if (session || sessionMessages.length > 0) {\n return {\n agentSessionId: normalizedAgentSessionId,\n source: \"none\",\n title: null\n };\n }\n\n const fallbackDisplayTitle = formatAgentGuiConversationPlainTitle(\n { title: fallbackTitle ?? \"\", titleFallback: null },\n { language }\n );\n return fallbackDisplayTitle\n ? {\n agentSessionId: normalizedAgentSessionId,\n source: \"fallback\",\n title: fallbackDisplayTitle\n }\n : {\n agentSessionId: normalizedAgentSessionId,\n source: \"none\",\n title: null\n };\n}\n\nfunction resolveDisplayableSnapshotSessionTitle(input: {\n messages: readonly AgentActivityMessage[];\n provider: AgentGUIResolvedProvider;\n sessionTitle: string;\n language?: UiLanguage;\n}): string {\n const explicitSessionTitle = explicitConversationTitle({\n language: input.language,\n provider: input.provider,\n title: input.sessionTitle\n });\n if (explicitSessionTitle) {\n return explicitSessionTitle;\n }\n return explicitConversationTitle({\n language: input.language,\n provider: input.provider,\n title: firstAgentGUIUserMessageTitle(input.messages)\n });\n}\n\nfunction explicitConversationTitle(input: {\n language?: UiLanguage;\n provider: AgentGUIResolvedProvider;\n title: string | null | undefined;\n}): string {\n return (\n resolveAgentGUIExplicitConversationTitle({\n provider: input.provider,\n title: formatAgentGuiConversationPlainTitle(\n { title: input.title ?? \"\", titleFallback: null },\n { language: input.language }\n ),\n titleFallback: null\n }) ?? \"\"\n );\n}\n"],"mappings":";;;;;;;;;AAiCO,SAAS,gCACd,OACA,UAA6C,CAAC,GACtC;AACR,SAAO,8BAA8B,OAAO,EAAE,UAAU,QAAQ,SAAS,CAAC;AAC5E;AAEO,SAAS,qCACd,cAIA,UAA6C,CAAC,GACtC;AACR,SAAO,qCAAqC,cAAc,OAAO;AACnE;AAEO,SAAS,qCAAqC;AAAA,EACnD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmF;AACjF,QAAM,2BAA2B,gBAAgB,KAAK,KAAK;AAC3D,MAAI,CAAC,0BAA0B;AAC7B,WAAO,EAAE,gBAAgB,MAAM,QAAQ,QAAQ,OAAO,KAAK;AAAA,EAC7D;AAEA,QAAM,UAAU,SAAS,SAAS;AAAA,IAChC,CAAC,SAAS,KAAK,mBAAmB;AAAA,EACpC;AACA,QAAM,kBACJ,SAAS,oBAAoB,wBAAwB,KAAK,CAAC;AAC7D,QAAM,qBAAqB;AAAA,IACzB,SAAS,YAAY;AAAA,EACvB;AACA,QAAM,gBAAgB,uCAAuC;AAAA,IAC3D,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc,SAAS,SAAS;AAAA,IAChC;AAAA,EACF,CAAC;AACD,MAAI,eAAe;AACjB,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,WAAW,gBAAgB,SAAS,GAAG;AACzC,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,uBAAuB;AAAA,IAC3B,EAAE,OAAO,iBAAiB,IAAI,eAAe,KAAK;AAAA,IAClD,EAAE,SAAS;AAAA,EACb;AACA,SAAO,uBACH;AAAA,IACE,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,IACA;AAAA,IACE,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AACN;AAEA,SAAS,uCAAuC,OAKrC;AACT,QAAM,uBAAuB,0BAA0B;AAAA,IACrD,UAAU,MAAM;AAAA,IAChB,UAAU,MAAM;AAAA,IAChB,OAAO,MAAM;AAAA,EACf,CAAC;AACD,MAAI,sBAAsB;AACxB,WAAO;AAAA,EACT;AACA,SAAO,0BAA0B;AAAA,IAC/B,UAAU,MAAM;AAAA,IAChB,UAAU,MAAM;AAAA,IAChB,OAAO,8BAA8B,MAAM,QAAQ;AAAA,EACrD,CAAC;AACH;AAEA,SAAS,0BAA0B,OAIxB;AACT,SACE,yCAAyC;AAAA,IACvC,UAAU,MAAM;AAAA,IAChB,OAAO;AAAA,MACL,EAAE,OAAO,MAAM,SAAS,IAAI,eAAe,KAAK;AAAA,MAChD,EAAE,UAAU,MAAM,SAAS;AAAA,IAC7B;AAAA,IACA,eAAe;AAAA,EACjB,CAAC,KAAK;AAEV;","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
translate,
|
|
7
7
|
useTranslation
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-EIC7XS3C.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveAgentWorkspaceFileVisualKind
|
|
11
11
|
} from "./chunk-PJP5BUU6.js";
|
|
@@ -204,13 +204,17 @@ import {
|
|
|
204
204
|
useEffect,
|
|
205
205
|
useState as useState2
|
|
206
206
|
} from "react";
|
|
207
|
+
import { createPortal } from "react-dom";
|
|
207
208
|
import {
|
|
209
|
+
Button,
|
|
208
210
|
ToastProvider,
|
|
209
211
|
ToastRoot,
|
|
210
212
|
ToastTitle,
|
|
211
|
-
ToastViewport
|
|
213
|
+
ToastViewport,
|
|
214
|
+
CopyIcon,
|
|
215
|
+
DownloadIcon,
|
|
216
|
+
RestoreIcon
|
|
212
217
|
} from "@tutti-os/ui-system";
|
|
213
|
-
import { CopyIcon, DownloadIcon } from "lucide-react";
|
|
214
218
|
import Zoom from "react-medium-image-zoom";
|
|
215
219
|
|
|
216
220
|
// app/renderer/lib/utils.ts
|
|
@@ -498,12 +502,20 @@ function ZoomableImage({
|
|
|
498
502
|
)
|
|
499
503
|
}
|
|
500
504
|
) : null,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
505
|
+
/* @__PURE__ */ jsx2(
|
|
506
|
+
Button,
|
|
507
|
+
{
|
|
508
|
+
asChild: true,
|
|
509
|
+
className: "tsh-zoom-dialog__icon-button nodrag tsh-desktop-no-drag",
|
|
510
|
+
size: "icon",
|
|
511
|
+
variant: "chrome",
|
|
512
|
+
children: cloneElement(
|
|
513
|
+
buttonUnzoom,
|
|
514
|
+
void 0,
|
|
515
|
+
/* @__PURE__ */ jsx2(RestoreIcon, { "aria-hidden": "true", className: "size-4" })
|
|
516
|
+
)
|
|
517
|
+
}
|
|
518
|
+
)
|
|
507
519
|
] });
|
|
508
520
|
};
|
|
509
521
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
@@ -550,18 +562,21 @@ function ZoomableImage({
|
|
|
550
562
|
)
|
|
551
563
|
}
|
|
552
564
|
) : null,
|
|
553
|
-
copyStatus ?
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
565
|
+
copyStatus ? createPortal(
|
|
566
|
+
/* @__PURE__ */ jsx2(
|
|
567
|
+
ImageCopyStatusToast,
|
|
568
|
+
{
|
|
569
|
+
busy: copyStatus.busy,
|
|
570
|
+
message: copyStatus.message,
|
|
571
|
+
variant: copyStatus.variant,
|
|
572
|
+
onOpenChange: (open) => {
|
|
573
|
+
if (!open) {
|
|
574
|
+
setCopyStatus(null);
|
|
575
|
+
}
|
|
562
576
|
}
|
|
563
577
|
}
|
|
564
|
-
|
|
578
|
+
),
|
|
579
|
+
document.body
|
|
565
580
|
) : null
|
|
566
581
|
] });
|
|
567
582
|
}
|
|
@@ -602,6 +617,42 @@ function ImageActionButtons({
|
|
|
602
617
|
onCopy,
|
|
603
618
|
onDownload
|
|
604
619
|
}) {
|
|
620
|
+
if (!itemRole) {
|
|
621
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
622
|
+
/* @__PURE__ */ jsx2(
|
|
623
|
+
Button,
|
|
624
|
+
{
|
|
625
|
+
"aria-label": copyLabel,
|
|
626
|
+
className: "tsh-zoom-dialog__icon-button",
|
|
627
|
+
size: "icon",
|
|
628
|
+
title: copyLabel,
|
|
629
|
+
variant: "chrome",
|
|
630
|
+
onClick: (event) => {
|
|
631
|
+
event.preventDefault();
|
|
632
|
+
event.stopPropagation();
|
|
633
|
+
onCopy();
|
|
634
|
+
},
|
|
635
|
+
children: /* @__PURE__ */ jsx2(CopyIcon, { "aria-hidden": "true", className: "size-4" })
|
|
636
|
+
}
|
|
637
|
+
),
|
|
638
|
+
/* @__PURE__ */ jsx2(
|
|
639
|
+
Button,
|
|
640
|
+
{
|
|
641
|
+
"aria-label": downloadLabel,
|
|
642
|
+
className: "tsh-zoom-dialog__icon-button",
|
|
643
|
+
size: "icon",
|
|
644
|
+
title: downloadLabel,
|
|
645
|
+
variant: "chrome",
|
|
646
|
+
onClick: (event) => {
|
|
647
|
+
event.preventDefault();
|
|
648
|
+
event.stopPropagation();
|
|
649
|
+
onDownload();
|
|
650
|
+
},
|
|
651
|
+
children: /* @__PURE__ */ jsx2(DownloadIcon, { "aria-hidden": "true", className: "size-4" })
|
|
652
|
+
}
|
|
653
|
+
)
|
|
654
|
+
] });
|
|
655
|
+
}
|
|
605
656
|
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
606
657
|
/* @__PURE__ */ jsxs2(
|
|
607
658
|
"button",
|
|
@@ -3210,4 +3261,4 @@ export {
|
|
|
3210
3261
|
CustomScrollArea,
|
|
3211
3262
|
MessageSquareMoreIcon
|
|
3212
3263
|
};
|
|
3213
|
-
//# sourceMappingURL=chunk-
|
|
3264
|
+
//# sourceMappingURL=chunk-QT45WUPQ.js.map
|