@athenaintel/react 0.42.2 → 0.43.0
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/README.md +10 -0
- package/dist/agent-runtime/src/conversation-list-groups.d.ts +74 -0
- package/dist/agent-runtime/src/index.d.ts +1 -0
- package/dist/agent-runtime/src/tool-metadata.cjs +0 -8
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +0 -8
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +30 -15
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +8 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.js +30 -15
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +8 -2
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +6 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +8 -2
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.cjs +27 -0
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +5 -1
- package/dist/chat/super-grouping/ToolTimeline.js +27 -0
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +1 -0
- package/dist/chat/super-grouping/timeline-step.cjs +61 -2
- package/dist/chat/super-grouping/timeline-step.cjs.map +1 -1
- package/dist/chat/super-grouping/timeline-step.d.ts +13 -1
- package/dist/chat/super-grouping/timeline-step.js +61 -2
- package/dist/chat/super-grouping/timeline-step.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +144 -35
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.d.ts +17 -1
- package/dist/chat-ui/mentions/mention-chip.js +146 -37
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/use-mention-asset.cjs +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-mention-asset.d.ts +16 -0
- package/dist/chat-ui/mentions/use-mention-asset.js +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.js.map +1 -0
- package/dist/chat-ui/rich-text/chat-link.cjs +5 -4
- package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.d.ts +2 -3
- package/dist/chat-ui/rich-text/chat-link.js +6 -5
- package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.cjs +1 -0
- package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.js +1 -0
- package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/tool-option-schemas.d.ts +0 -34
- package/dist/styles.css +1 -1
- package/dist/threads/statewire-thread-list.cjs +6 -2
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.js +6 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/tools/tool-summary.cjs +0 -2
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +0 -2
- package/dist/tools/tool-summary.js.map +1 -1
- package/package.json +1 -1
|
@@ -15,6 +15,7 @@ export { GroupedMessageParts, type GroupedMessagePartsProps } from './GroupedMes
|
|
|
15
15
|
export { createToolBasedGroupingFunction, type GroupablePart, type GroupingFunction, type MessagePartGroup, } from './grouping-function';
|
|
16
16
|
export { resetRememberedExpansionsForTests, SuperGroupingCard, type SuperGroupingCardProps, SuperGroupingFinalText, useActivityExpansion, } from './SuperGroupingCard';
|
|
17
17
|
export { SuperGroupingTranscript, type SuperGroupingTranscriptProps } from './SuperGroupingTranscript';
|
|
18
|
+
export type { TimelineStep } from './timeline-step';
|
|
18
19
|
export { scopeGroupingToSegment, type SegmentablePart, type SegmentSummary, splitTurnSegments, summarizeSegment, type TurnSegment, } from './turn-segments';
|
|
19
20
|
export { formatWorkDuration, readTurnTiming, type TurnTiming, type TurnTimingSources, workedDurationMs, } from './turn-timing';
|
|
20
21
|
export { defaultGetToolGroupKey, type GetToolGroupKey, type ToolGroupKeyOptions } from './toolkit-map';
|
|
@@ -30,7 +30,8 @@ function toTimelineStep({
|
|
|
30
30
|
item,
|
|
31
31
|
index,
|
|
32
32
|
resolveToolDisplayName,
|
|
33
|
-
assetTitles
|
|
33
|
+
assetTitles,
|
|
34
|
+
withSourceUrls = false
|
|
34
35
|
}) {
|
|
35
36
|
const id = item.id ?? `${item.kind}-${index}`;
|
|
36
37
|
if (item.kind !== "tool") {
|
|
@@ -44,8 +45,13 @@ function toTimelineStep({
|
|
|
44
45
|
...summary.detail ? { detail: summary.detail } : {},
|
|
45
46
|
...summary.meta ? { chip: summary.meta } : {},
|
|
46
47
|
state: item.state,
|
|
47
|
-
kind: item.kind
|
|
48
|
+
kind: item.kind,
|
|
49
|
+
toolName: item.toolName
|
|
48
50
|
};
|
|
51
|
+
if (withSourceUrls && item.state === "complete") {
|
|
52
|
+
const sourceUrls = collectSourceUrls(item.result);
|
|
53
|
+
if (sourceUrls.length > 0) step.sourceUrls = sourceUrls;
|
|
54
|
+
}
|
|
49
55
|
const args = item.args;
|
|
50
56
|
if (!args || !item.toolName.startsWith("chrome_")) return step;
|
|
51
57
|
const tabId = args.tabId ?? args.tab_id;
|
|
@@ -69,6 +75,59 @@ function visibleTimelineSteps({ steps, limit }) {
|
|
|
69
75
|
(step, index) => index >= steps.length - safeLimit || step.state === "running" || step.state === "waiting"
|
|
70
76
|
);
|
|
71
77
|
}
|
|
78
|
+
const SOURCE_URL_KEYS = ["url", "link", "href"];
|
|
79
|
+
const MAX_SOURCE_URLS = 3;
|
|
80
|
+
const MAX_SOURCE_DEPTH = 4;
|
|
81
|
+
const MAX_SOURCE_RESULT_CHARS = 256 * 1024;
|
|
82
|
+
function parseJson(text) {
|
|
83
|
+
if (text.length > MAX_SOURCE_RESULT_CHARS) return void 0;
|
|
84
|
+
try {
|
|
85
|
+
return JSON.parse(text);
|
|
86
|
+
} catch {
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function parseResult(result) {
|
|
91
|
+
if (typeof result === "string") return parseJson(result);
|
|
92
|
+
if (Array.isArray(result) && result.length > 0 && result.every(isTextBlock)) {
|
|
93
|
+
return parseJson(result.map((block) => block.text).join(""));
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function isTextBlock(value) {
|
|
98
|
+
if (typeof value !== "object" || value === null) return false;
|
|
99
|
+
const block = value;
|
|
100
|
+
return block.type === "text" && typeof block.text === "string";
|
|
101
|
+
}
|
|
102
|
+
function collectSourceUrls(result) {
|
|
103
|
+
const urls = [];
|
|
104
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
105
|
+
const visit = ({ value, depth }) => {
|
|
106
|
+
if (urls.length >= MAX_SOURCE_URLS || depth > MAX_SOURCE_DEPTH || value === null) return;
|
|
107
|
+
if (Array.isArray(value)) {
|
|
108
|
+
for (const entry of value) visit({ value: entry, depth: depth + 1 });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (typeof value !== "object") return;
|
|
112
|
+
const record = value;
|
|
113
|
+
for (const key of SOURCE_URL_KEYS) {
|
|
114
|
+
const candidate = record[key];
|
|
115
|
+
if (typeof candidate !== "string") continue;
|
|
116
|
+
const host = pageTarget(candidate);
|
|
117
|
+
if (host && !hosts.has(host)) {
|
|
118
|
+
hosts.add(host);
|
|
119
|
+
urls.push(candidate);
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
for (const entry of Object.values(record)) {
|
|
124
|
+
if (typeof entry === "object") visit({ value: entry, depth: depth + 1 });
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
visit({ value: parseResult(result), depth: 0 });
|
|
128
|
+
return urls;
|
|
129
|
+
}
|
|
130
|
+
exports.collectSourceUrls = collectSourceUrls;
|
|
72
131
|
exports.toTimelineStep = toTimelineStep;
|
|
73
132
|
exports.visibleTimelineSteps = visibleTimelineSteps;
|
|
74
133
|
//# sourceMappingURL=timeline-step.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-step.cjs","sources":["../../../src/chat/super-grouping/timeline-step.ts"],"sourcesContent":["import { type ActivityItem, getReasoningLabel, summarizeActivityTool } from './activity-timeline';\n\nexport interface TimelineStep {\n id: string;\n /** The row's line (\"Ran git status\"); `code` marks the literal part of it. */\n verb: string;\n /** The span of `verb` that is literal code (a command, a file name, a pattern). */\n code?: string;\n /** Longer form for the row's tooltip (the full path, the whole command line). */\n detail?: string;\n /** A short chip after the line (\"+4 −1\", \"on jevin-box\", \"Tab 7\"). */\n chip?: string;\n state: ActivityItem['state'];\n kind: ActivityItem['kind'];\n}\n\nconst COMPUTER_ACTIONS: Record<string, readonly [string, string]> = {\n screenshot: ['Taking screenshot', 'Took screenshot'],\n left_click: ['Clicking', 'Clicked'],\n right_click: ['Right-clicking', 'Right-clicked'],\n double_click: ['Double-clicking', 'Double-clicked'],\n triple_click: ['Triple-clicking', 'Triple-clicked'],\n type: ['Typing', 'Typed'],\n key: ['Pressing keys', 'Pressed keys'],\n scroll: ['Scrolling', 'Scrolled'],\n scroll_to: ['Scrolling to element', 'Scrolled to element'],\n zoom: ['Zooming', 'Zoomed'],\n hover: ['Hovering', 'Hovered'],\n left_click_drag: ['Dragging', 'Dragged'],\n wait: ['Waiting', 'Waited'],\n};\n\n/** Keep credentials, query strings, fragments, and typed input out of summary chips. */\nfunction pageTarget(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\nexport function toTimelineStep({\n item,\n index,\n resolveToolDisplayName,\n assetTitles,\n}: {\n item: ActivityItem;\n index: number;\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Titles for asset ids earlier results in the turn named (see `collectAssetTitles`). */\n assetTitles?: ReadonlyMap<string, string>;\n}): TimelineStep {\n const id = item.id ?? `${item.kind}-${index}`;\n if (item.kind !== 'tool') {\n return { id, verb: getReasoningLabel(item.text, item.state), state: item.state, kind: item.kind };\n }\n const summary = summarizeActivityTool(item, resolveToolDisplayName, assetTitles);\n const step: TimelineStep = {\n id,\n verb: summary.label,\n ...(summary.code ? { code: summary.code } : {}),\n ...(summary.detail ? { detail: summary.detail } : {}),\n ...(summary.meta ? { chip: summary.meta } : {}),\n state: item.state,\n kind: item.kind,\n };\n const args = item.args;\n if (!args || !item.toolName.startsWith('chrome_')) return step;\n\n const tabId = args.tabId ?? args.tab_id;\n step.chip = pageTarget(args.url) ?? (typeof tabId === 'number' ? `Tab ${tabId}` : undefined);\n // Only successful/live actions get action-specific tense. Failure, rejection,\n // cancellation and approval copy continues to come from the shared classifier.\n if (item.state !== 'running' && item.state !== 'complete') return step;\n if (item.toolName === 'chrome_computer' && typeof args.action === 'string') {\n const action = COMPUTER_ACTIONS[args.action];\n if (action) step.verb = action[item.state === 'running' ? 0 : 1];\n } else if (item.toolName === 'chrome_navigate') {\n step.verb = item.state === 'running' ? 'Navigating to' : 'Navigated to';\n } else if (item.toolName === 'chrome_batch' && Array.isArray(args.steps)) {\n const count = args.steps.length;\n step.verb = item.state === 'running' ? 'Running Chrome actions' : 'Completed Chrome actions';\n step.chip = `${count} ${count === 1 ? 'action' : 'actions'}`;\n }\n return step;\n}\n\n/** Every unresolved parallel call stays visible even when older settled steps fold away. */\nexport function visibleTimelineSteps({ steps, limit }: { steps: readonly TimelineStep[]; limit: number }) {\n const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 3;\n return steps.filter(\n (step, index) =>\n index >= steps.length - safeLimit || step.state === 'running' || step.state === 'waiting',\n );\n}\n"],"names":["getReasoningLabel","summarizeActivityTool"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"timeline-step.cjs","sources":["../../../src/chat/super-grouping/timeline-step.ts"],"sourcesContent":["import { type ActivityItem, getReasoningLabel, summarizeActivityTool } from './activity-timeline';\n\nexport interface TimelineStep {\n id: string;\n /** The row's line (\"Ran git status\"); `code` marks the literal part of it. */\n verb: string;\n /** The span of `verb` that is literal code (a command, a file name, a pattern). */\n code?: string;\n /** Longer form for the row's tooltip (the full path, the whole command line). */\n detail?: string;\n /** A short chip after the line (\"+4 −1\", \"on jevin-box\", \"Tab 7\"). */\n chip?: string;\n state: ActivityItem['state'];\n kind: ActivityItem['kind'];\n /** The tool a `tool` step called, so a host can show that tool's icon. */\n toolName?: string;\n /** Web pages a finished step's result names (up to three, one per site), for their favicons. */\n sourceUrls?: readonly string[];\n}\n\nconst COMPUTER_ACTIONS: Record<string, readonly [string, string]> = {\n screenshot: ['Taking screenshot', 'Took screenshot'],\n left_click: ['Clicking', 'Clicked'],\n right_click: ['Right-clicking', 'Right-clicked'],\n double_click: ['Double-clicking', 'Double-clicked'],\n triple_click: ['Triple-clicking', 'Triple-clicked'],\n type: ['Typing', 'Typed'],\n key: ['Pressing keys', 'Pressed keys'],\n scroll: ['Scrolling', 'Scrolled'],\n scroll_to: ['Scrolling to element', 'Scrolled to element'],\n zoom: ['Zooming', 'Zoomed'],\n hover: ['Hovering', 'Hovered'],\n left_click_drag: ['Dragging', 'Dragged'],\n wait: ['Waiting', 'Waited'],\n};\n\n/** Keep credentials, query strings, fragments, and typed input out of summary chips. */\nfunction pageTarget(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\nexport function toTimelineStep({\n item,\n index,\n resolveToolDisplayName,\n assetTitles,\n withSourceUrls = false,\n}: {\n item: ActivityItem;\n index: number;\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Titles for asset ids earlier results in the turn named (see `collectAssetTitles`). */\n assetTitles?: ReadonlyMap<string, string>;\n /** Read the web pages a finished result names into `sourceUrls` (only when the card shows favicons). */\n withSourceUrls?: boolean;\n}): TimelineStep {\n const id = item.id ?? `${item.kind}-${index}`;\n if (item.kind !== 'tool') {\n return { id, verb: getReasoningLabel(item.text, item.state), state: item.state, kind: item.kind };\n }\n const summary = summarizeActivityTool(item, resolveToolDisplayName, assetTitles);\n const step: TimelineStep = {\n id,\n verb: summary.label,\n ...(summary.code ? { code: summary.code } : {}),\n ...(summary.detail ? { detail: summary.detail } : {}),\n ...(summary.meta ? { chip: summary.meta } : {}),\n state: item.state,\n kind: item.kind,\n toolName: item.toolName,\n };\n if (withSourceUrls && item.state === 'complete') {\n const sourceUrls = collectSourceUrls(item.result);\n if (sourceUrls.length > 0) step.sourceUrls = sourceUrls;\n }\n const args = item.args;\n if (!args || !item.toolName.startsWith('chrome_')) return step;\n\n const tabId = args.tabId ?? args.tab_id;\n step.chip = pageTarget(args.url) ?? (typeof tabId === 'number' ? `Tab ${tabId}` : undefined);\n // Only successful/live actions get action-specific tense. Failure, rejection,\n // cancellation and approval copy continues to come from the shared classifier.\n if (item.state !== 'running' && item.state !== 'complete') return step;\n if (item.toolName === 'chrome_computer' && typeof args.action === 'string') {\n const action = COMPUTER_ACTIONS[args.action];\n if (action) step.verb = action[item.state === 'running' ? 0 : 1];\n } else if (item.toolName === 'chrome_navigate') {\n step.verb = item.state === 'running' ? 'Navigating to' : 'Navigated to';\n } else if (item.toolName === 'chrome_batch' && Array.isArray(args.steps)) {\n const count = args.steps.length;\n step.verb = item.state === 'running' ? 'Running Chrome actions' : 'Completed Chrome actions';\n step.chip = `${count} ${count === 1 ? 'action' : 'actions'}`;\n }\n return step;\n}\n\n/** Every unresolved parallel call stays visible even when older settled steps fold away. */\nexport function visibleTimelineSteps({ steps, limit }: { steps: readonly TimelineStep[]; limit: number }) {\n const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 3;\n return steps.filter(\n (step, index) =>\n index >= steps.length - safeLimit || step.state === 'running' || step.state === 'waiting',\n );\n}\n\nconst SOURCE_URL_KEYS = ['url', 'link', 'href'] as const;\nconst MAX_SOURCE_URLS = 3;\nconst MAX_SOURCE_DEPTH = 4;\n\nconst MAX_SOURCE_RESULT_CHARS = 256 * 1024;\n\nfunction parseJson(text: string): unknown {\n if (text.length > MAX_SOURCE_RESULT_CHARS) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/** A result as JSON: an object, a JSON string, or LangChain text blocks holding JSON. */\nfunction parseResult(result: unknown): unknown {\n if (typeof result === 'string') return parseJson(result);\n if (Array.isArray(result) && result.length > 0 && result.every(isTextBlock)) {\n return parseJson(result.map((block) => block.text).join(''));\n }\n return result;\n}\n\nfunction isTextBlock(value: unknown): value is { type: 'text'; text: string } {\n if (typeof value !== 'object' || value === null) return false;\n const block = value as Record<string, unknown>;\n return block.type === 'text' && typeof block.text === 'string';\n}\n\n/**\n * The web pages a tool result lists (a search's `results[].url`), at most one\n * per site and three in all, in the order the result gives them. Only http(s)\n * links count; anything else in the result is ignored.\n */\nexport function collectSourceUrls(result: unknown): string[] {\n const urls: string[] = [];\n const hosts = new Set<string>();\n const visit = ({ value, depth }: { value: unknown; depth: number }): void => {\n if (urls.length >= MAX_SOURCE_URLS || depth > MAX_SOURCE_DEPTH || value === null) return;\n if (Array.isArray(value)) {\n for (const entry of value) visit({ value: entry, depth: depth + 1 });\n return;\n }\n if (typeof value !== 'object') return;\n const record = value as Record<string, unknown>;\n for (const key of SOURCE_URL_KEYS) {\n const candidate = record[key];\n if (typeof candidate !== 'string') continue;\n const host = pageTarget(candidate);\n if (host && !hosts.has(host)) {\n hosts.add(host);\n urls.push(candidate);\n }\n break;\n }\n for (const entry of Object.values(record)) {\n if (typeof entry === 'object') visit({ value: entry, depth: depth + 1 });\n }\n };\n visit({ value: parseResult(result), depth: 0 });\n return urls;\n}\n"],"names":["getReasoningLabel","summarizeActivityTool"],"mappings":"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"}
|
|
@@ -11,16 +11,28 @@ export interface TimelineStep {
|
|
|
11
11
|
chip?: string;
|
|
12
12
|
state: ActivityItem['state'];
|
|
13
13
|
kind: ActivityItem['kind'];
|
|
14
|
+
/** The tool a `tool` step called, so a host can show that tool's icon. */
|
|
15
|
+
toolName?: string;
|
|
16
|
+
/** Web pages a finished step's result names (up to three, one per site), for their favicons. */
|
|
17
|
+
sourceUrls?: readonly string[];
|
|
14
18
|
}
|
|
15
|
-
export declare function toTimelineStep({ item, index, resolveToolDisplayName, assetTitles, }: {
|
|
19
|
+
export declare function toTimelineStep({ item, index, resolveToolDisplayName, assetTitles, withSourceUrls, }: {
|
|
16
20
|
item: ActivityItem;
|
|
17
21
|
index: number;
|
|
18
22
|
resolveToolDisplayName?: (toolName: string) => string | undefined;
|
|
19
23
|
/** Titles for asset ids earlier results in the turn named (see `collectAssetTitles`). */
|
|
20
24
|
assetTitles?: ReadonlyMap<string, string>;
|
|
25
|
+
/** Read the web pages a finished result names into `sourceUrls` (only when the card shows favicons). */
|
|
26
|
+
withSourceUrls?: boolean;
|
|
21
27
|
}): TimelineStep;
|
|
22
28
|
/** Every unresolved parallel call stays visible even when older settled steps fold away. */
|
|
23
29
|
export declare function visibleTimelineSteps({ steps, limit }: {
|
|
24
30
|
steps: readonly TimelineStep[];
|
|
25
31
|
limit: number;
|
|
26
32
|
}): TimelineStep[];
|
|
33
|
+
/**
|
|
34
|
+
* The web pages a tool result lists (a search's `results[].url`), at most one
|
|
35
|
+
* per site and three in all, in the order the result gives them. Only http(s)
|
|
36
|
+
* links count; anything else in the result is ignored.
|
|
37
|
+
*/
|
|
38
|
+
export declare function collectSourceUrls(result: unknown): string[];
|
|
@@ -28,7 +28,8 @@ function toTimelineStep({
|
|
|
28
28
|
item,
|
|
29
29
|
index,
|
|
30
30
|
resolveToolDisplayName,
|
|
31
|
-
assetTitles
|
|
31
|
+
assetTitles,
|
|
32
|
+
withSourceUrls = false
|
|
32
33
|
}) {
|
|
33
34
|
const id = item.id ?? `${item.kind}-${index}`;
|
|
34
35
|
if (item.kind !== "tool") {
|
|
@@ -42,8 +43,13 @@ function toTimelineStep({
|
|
|
42
43
|
...summary.detail ? { detail: summary.detail } : {},
|
|
43
44
|
...summary.meta ? { chip: summary.meta } : {},
|
|
44
45
|
state: item.state,
|
|
45
|
-
kind: item.kind
|
|
46
|
+
kind: item.kind,
|
|
47
|
+
toolName: item.toolName
|
|
46
48
|
};
|
|
49
|
+
if (withSourceUrls && item.state === "complete") {
|
|
50
|
+
const sourceUrls = collectSourceUrls(item.result);
|
|
51
|
+
if (sourceUrls.length > 0) step.sourceUrls = sourceUrls;
|
|
52
|
+
}
|
|
47
53
|
const args = item.args;
|
|
48
54
|
if (!args || !item.toolName.startsWith("chrome_")) return step;
|
|
49
55
|
const tabId = args.tabId ?? args.tab_id;
|
|
@@ -67,7 +73,60 @@ function visibleTimelineSteps({ steps, limit }) {
|
|
|
67
73
|
(step, index) => index >= steps.length - safeLimit || step.state === "running" || step.state === "waiting"
|
|
68
74
|
);
|
|
69
75
|
}
|
|
76
|
+
const SOURCE_URL_KEYS = ["url", "link", "href"];
|
|
77
|
+
const MAX_SOURCE_URLS = 3;
|
|
78
|
+
const MAX_SOURCE_DEPTH = 4;
|
|
79
|
+
const MAX_SOURCE_RESULT_CHARS = 256 * 1024;
|
|
80
|
+
function parseJson(text) {
|
|
81
|
+
if (text.length > MAX_SOURCE_RESULT_CHARS) return void 0;
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(text);
|
|
84
|
+
} catch {
|
|
85
|
+
return void 0;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function parseResult(result) {
|
|
89
|
+
if (typeof result === "string") return parseJson(result);
|
|
90
|
+
if (Array.isArray(result) && result.length > 0 && result.every(isTextBlock)) {
|
|
91
|
+
return parseJson(result.map((block) => block.text).join(""));
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function isTextBlock(value) {
|
|
96
|
+
if (typeof value !== "object" || value === null) return false;
|
|
97
|
+
const block = value;
|
|
98
|
+
return block.type === "text" && typeof block.text === "string";
|
|
99
|
+
}
|
|
100
|
+
function collectSourceUrls(result) {
|
|
101
|
+
const urls = [];
|
|
102
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
103
|
+
const visit = ({ value, depth }) => {
|
|
104
|
+
if (urls.length >= MAX_SOURCE_URLS || depth > MAX_SOURCE_DEPTH || value === null) return;
|
|
105
|
+
if (Array.isArray(value)) {
|
|
106
|
+
for (const entry of value) visit({ value: entry, depth: depth + 1 });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (typeof value !== "object") return;
|
|
110
|
+
const record = value;
|
|
111
|
+
for (const key of SOURCE_URL_KEYS) {
|
|
112
|
+
const candidate = record[key];
|
|
113
|
+
if (typeof candidate !== "string") continue;
|
|
114
|
+
const host = pageTarget(candidate);
|
|
115
|
+
if (host && !hosts.has(host)) {
|
|
116
|
+
hosts.add(host);
|
|
117
|
+
urls.push(candidate);
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
for (const entry of Object.values(record)) {
|
|
122
|
+
if (typeof entry === "object") visit({ value: entry, depth: depth + 1 });
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
visit({ value: parseResult(result), depth: 0 });
|
|
126
|
+
return urls;
|
|
127
|
+
}
|
|
70
128
|
export {
|
|
129
|
+
collectSourceUrls,
|
|
71
130
|
toTimelineStep,
|
|
72
131
|
visibleTimelineSteps
|
|
73
132
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-step.js","sources":["../../../src/chat/super-grouping/timeline-step.ts"],"sourcesContent":["import { type ActivityItem, getReasoningLabel, summarizeActivityTool } from './activity-timeline';\n\nexport interface TimelineStep {\n id: string;\n /** The row's line (\"Ran git status\"); `code` marks the literal part of it. */\n verb: string;\n /** The span of `verb` that is literal code (a command, a file name, a pattern). */\n code?: string;\n /** Longer form for the row's tooltip (the full path, the whole command line). */\n detail?: string;\n /** A short chip after the line (\"+4 −1\", \"on jevin-box\", \"Tab 7\"). */\n chip?: string;\n state: ActivityItem['state'];\n kind: ActivityItem['kind'];\n}\n\nconst COMPUTER_ACTIONS: Record<string, readonly [string, string]> = {\n screenshot: ['Taking screenshot', 'Took screenshot'],\n left_click: ['Clicking', 'Clicked'],\n right_click: ['Right-clicking', 'Right-clicked'],\n double_click: ['Double-clicking', 'Double-clicked'],\n triple_click: ['Triple-clicking', 'Triple-clicked'],\n type: ['Typing', 'Typed'],\n key: ['Pressing keys', 'Pressed keys'],\n scroll: ['Scrolling', 'Scrolled'],\n scroll_to: ['Scrolling to element', 'Scrolled to element'],\n zoom: ['Zooming', 'Zoomed'],\n hover: ['Hovering', 'Hovered'],\n left_click_drag: ['Dragging', 'Dragged'],\n wait: ['Waiting', 'Waited'],\n};\n\n/** Keep credentials, query strings, fragments, and typed input out of summary chips. */\nfunction pageTarget(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\nexport function toTimelineStep({\n item,\n index,\n resolveToolDisplayName,\n assetTitles,\n}: {\n item: ActivityItem;\n index: number;\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Titles for asset ids earlier results in the turn named (see `collectAssetTitles`). */\n assetTitles?: ReadonlyMap<string, string>;\n}): TimelineStep {\n const id = item.id ?? `${item.kind}-${index}`;\n if (item.kind !== 'tool') {\n return { id, verb: getReasoningLabel(item.text, item.state), state: item.state, kind: item.kind };\n }\n const summary = summarizeActivityTool(item, resolveToolDisplayName, assetTitles);\n const step: TimelineStep = {\n id,\n verb: summary.label,\n ...(summary.code ? { code: summary.code } : {}),\n ...(summary.detail ? { detail: summary.detail } : {}),\n ...(summary.meta ? { chip: summary.meta } : {}),\n state: item.state,\n kind: item.kind,\n };\n const args = item.args;\n if (!args || !item.toolName.startsWith('chrome_')) return step;\n\n const tabId = args.tabId ?? args.tab_id;\n step.chip = pageTarget(args.url) ?? (typeof tabId === 'number' ? `Tab ${tabId}` : undefined);\n // Only successful/live actions get action-specific tense. Failure, rejection,\n // cancellation and approval copy continues to come from the shared classifier.\n if (item.state !== 'running' && item.state !== 'complete') return step;\n if (item.toolName === 'chrome_computer' && typeof args.action === 'string') {\n const action = COMPUTER_ACTIONS[args.action];\n if (action) step.verb = action[item.state === 'running' ? 0 : 1];\n } else if (item.toolName === 'chrome_navigate') {\n step.verb = item.state === 'running' ? 'Navigating to' : 'Navigated to';\n } else if (item.toolName === 'chrome_batch' && Array.isArray(args.steps)) {\n const count = args.steps.length;\n step.verb = item.state === 'running' ? 'Running Chrome actions' : 'Completed Chrome actions';\n step.chip = `${count} ${count === 1 ? 'action' : 'actions'}`;\n }\n return step;\n}\n\n/** Every unresolved parallel call stays visible even when older settled steps fold away. */\nexport function visibleTimelineSteps({ steps, limit }: { steps: readonly TimelineStep[]; limit: number }) {\n const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 3;\n return steps.filter(\n (step, index) =>\n index >= steps.length - safeLimit || step.state === 'running' || step.state === 'waiting',\n );\n}\n"],"names":[],"mappings":";AAgBA,MAAM,mBAA8D;AAAA,EAClE,YAAY,CAAC,qBAAqB,iBAAiB;AAAA,EACnD,YAAY,CAAC,YAAY,SAAS;AAAA,EAClC,aAAa,CAAC,kBAAkB,eAAe;AAAA,EAC/C,cAAc,CAAC,mBAAmB,gBAAgB;AAAA,EAClD,cAAc,CAAC,mBAAmB,gBAAgB;AAAA,EAClD,MAAM,CAAC,UAAU,OAAO;AAAA,EACxB,KAAK,CAAC,iBAAiB,cAAc;AAAA,EACrC,QAAQ,CAAC,aAAa,UAAU;AAAA,EAChC,WAAW,CAAC,wBAAwB,qBAAqB;AAAA,EACzD,MAAM,CAAC,WAAW,QAAQ;AAAA,EAC1B,OAAO,CAAC,YAAY,SAAS;AAAA,EAC7B,iBAAiB,CAAC,YAAY,SAAS;AAAA,EACvC,MAAM,CAAC,WAAW,QAAQ;AAC5B;AAGA,SAAS,WAAW,OAAoC;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAI,IAAI,aAAa,WAAW,IAAI,aAAa,SAAU,QAAO;AAClE,WAAO,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMiB;AACf,QAAM,KAAK,KAAK,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK;AAC3C,MAAI,KAAK,SAAS,QAAQ;AACxB,WAAO,EAAE,IAAI,MAAM,kBAAkB,KAAK,MAAM,KAAK,KAAK,GAAG,OAAO,KAAK,OAAO,MAAM,KAAK,KAAA;AAAA,EAC7F;AACA,QAAM,UAAU,sBAAsB,MAAM,wBAAwB,WAAW;AAC/E,QAAM,OAAqB;AAAA,IACzB;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAA,IAAS,CAAA;AAAA,IAC5C,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAA,IAAW,CAAA;AAAA,IAClD,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAA,IAAS,CAAA;AAAA,IAC5C,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,EAAA;AAEb,QAAM,OAAO,KAAK;AAClB,MAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,WAAW,SAAS,EAAG,QAAO;AAE1D,QAAM,QAAQ,KAAK,SAAS,KAAK;AACjC,OAAK,OAAO,WAAW,KAAK,GAAG,MAAM,OAAO,UAAU,WAAW,OAAO,KAAK,KAAK;AAGlF,MAAI,KAAK,UAAU,aAAa,KAAK,UAAU,WAAY,QAAO;AAClE,MAAI,KAAK,aAAa,qBAAqB,OAAO,KAAK,WAAW,UAAU;AAC1E,UAAM,SAAS,iBAAiB,KAAK,MAAM;AAC3C,QAAI,aAAa,OAAO,OAAO,KAAK,UAAU,YAAY,IAAI,CAAC;AAAA,EACjE,WAAW,KAAK,aAAa,mBAAmB;AAC9C,SAAK,OAAO,KAAK,UAAU,YAAY,kBAAkB;AAAA,EAC3D,WAAW,KAAK,aAAa,kBAAkB,MAAM,QAAQ,KAAK,KAAK,GAAG;AACxE,UAAM,QAAQ,KAAK,MAAM;AACzB,SAAK,OAAO,KAAK,UAAU,YAAY,2BAA2B;AAClE,SAAK,OAAO,GAAG,KAAK,IAAI,UAAU,IAAI,WAAW,SAAS;AAAA,EAC5D;AACA,SAAO;AACT;AAGO,SAAS,qBAAqB,EAAE,OAAO,SAA4D;AACxG,QAAM,YAAY,OAAO,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI;AAC5E,SAAO,MAAM;AAAA,IACX,CAAC,MAAM,UACL,SAAS,MAAM,SAAS,aAAa,KAAK,UAAU,aAAa,KAAK,UAAU;AAAA,EAAA;AAEtF;"}
|
|
1
|
+
{"version":3,"file":"timeline-step.js","sources":["../../../src/chat/super-grouping/timeline-step.ts"],"sourcesContent":["import { type ActivityItem, getReasoningLabel, summarizeActivityTool } from './activity-timeline';\n\nexport interface TimelineStep {\n id: string;\n /** The row's line (\"Ran git status\"); `code` marks the literal part of it. */\n verb: string;\n /** The span of `verb` that is literal code (a command, a file name, a pattern). */\n code?: string;\n /** Longer form for the row's tooltip (the full path, the whole command line). */\n detail?: string;\n /** A short chip after the line (\"+4 −1\", \"on jevin-box\", \"Tab 7\"). */\n chip?: string;\n state: ActivityItem['state'];\n kind: ActivityItem['kind'];\n /** The tool a `tool` step called, so a host can show that tool's icon. */\n toolName?: string;\n /** Web pages a finished step's result names (up to three, one per site), for their favicons. */\n sourceUrls?: readonly string[];\n}\n\nconst COMPUTER_ACTIONS: Record<string, readonly [string, string]> = {\n screenshot: ['Taking screenshot', 'Took screenshot'],\n left_click: ['Clicking', 'Clicked'],\n right_click: ['Right-clicking', 'Right-clicked'],\n double_click: ['Double-clicking', 'Double-clicked'],\n triple_click: ['Triple-clicking', 'Triple-clicked'],\n type: ['Typing', 'Typed'],\n key: ['Pressing keys', 'Pressed keys'],\n scroll: ['Scrolling', 'Scrolled'],\n scroll_to: ['Scrolling to element', 'Scrolled to element'],\n zoom: ['Zooming', 'Zoomed'],\n hover: ['Hovering', 'Hovered'],\n left_click_drag: ['Dragging', 'Dragged'],\n wait: ['Waiting', 'Waited'],\n};\n\n/** Keep credentials, query strings, fragments, and typed input out of summary chips. */\nfunction pageTarget(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n try {\n const url = new URL(value);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined;\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\nexport function toTimelineStep({\n item,\n index,\n resolveToolDisplayName,\n assetTitles,\n withSourceUrls = false,\n}: {\n item: ActivityItem;\n index: number;\n resolveToolDisplayName?: (toolName: string) => string | undefined;\n /** Titles for asset ids earlier results in the turn named (see `collectAssetTitles`). */\n assetTitles?: ReadonlyMap<string, string>;\n /** Read the web pages a finished result names into `sourceUrls` (only when the card shows favicons). */\n withSourceUrls?: boolean;\n}): TimelineStep {\n const id = item.id ?? `${item.kind}-${index}`;\n if (item.kind !== 'tool') {\n return { id, verb: getReasoningLabel(item.text, item.state), state: item.state, kind: item.kind };\n }\n const summary = summarizeActivityTool(item, resolveToolDisplayName, assetTitles);\n const step: TimelineStep = {\n id,\n verb: summary.label,\n ...(summary.code ? { code: summary.code } : {}),\n ...(summary.detail ? { detail: summary.detail } : {}),\n ...(summary.meta ? { chip: summary.meta } : {}),\n state: item.state,\n kind: item.kind,\n toolName: item.toolName,\n };\n if (withSourceUrls && item.state === 'complete') {\n const sourceUrls = collectSourceUrls(item.result);\n if (sourceUrls.length > 0) step.sourceUrls = sourceUrls;\n }\n const args = item.args;\n if (!args || !item.toolName.startsWith('chrome_')) return step;\n\n const tabId = args.tabId ?? args.tab_id;\n step.chip = pageTarget(args.url) ?? (typeof tabId === 'number' ? `Tab ${tabId}` : undefined);\n // Only successful/live actions get action-specific tense. Failure, rejection,\n // cancellation and approval copy continues to come from the shared classifier.\n if (item.state !== 'running' && item.state !== 'complete') return step;\n if (item.toolName === 'chrome_computer' && typeof args.action === 'string') {\n const action = COMPUTER_ACTIONS[args.action];\n if (action) step.verb = action[item.state === 'running' ? 0 : 1];\n } else if (item.toolName === 'chrome_navigate') {\n step.verb = item.state === 'running' ? 'Navigating to' : 'Navigated to';\n } else if (item.toolName === 'chrome_batch' && Array.isArray(args.steps)) {\n const count = args.steps.length;\n step.verb = item.state === 'running' ? 'Running Chrome actions' : 'Completed Chrome actions';\n step.chip = `${count} ${count === 1 ? 'action' : 'actions'}`;\n }\n return step;\n}\n\n/** Every unresolved parallel call stays visible even when older settled steps fold away. */\nexport function visibleTimelineSteps({ steps, limit }: { steps: readonly TimelineStep[]; limit: number }) {\n const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.floor(limit)) : 3;\n return steps.filter(\n (step, index) =>\n index >= steps.length - safeLimit || step.state === 'running' || step.state === 'waiting',\n );\n}\n\nconst SOURCE_URL_KEYS = ['url', 'link', 'href'] as const;\nconst MAX_SOURCE_URLS = 3;\nconst MAX_SOURCE_DEPTH = 4;\n\nconst MAX_SOURCE_RESULT_CHARS = 256 * 1024;\n\nfunction parseJson(text: string): unknown {\n if (text.length > MAX_SOURCE_RESULT_CHARS) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/** A result as JSON: an object, a JSON string, or LangChain text blocks holding JSON. */\nfunction parseResult(result: unknown): unknown {\n if (typeof result === 'string') return parseJson(result);\n if (Array.isArray(result) && result.length > 0 && result.every(isTextBlock)) {\n return parseJson(result.map((block) => block.text).join(''));\n }\n return result;\n}\n\nfunction isTextBlock(value: unknown): value is { type: 'text'; text: string } {\n if (typeof value !== 'object' || value === null) return false;\n const block = value as Record<string, unknown>;\n return block.type === 'text' && typeof block.text === 'string';\n}\n\n/**\n * The web pages a tool result lists (a search's `results[].url`), at most one\n * per site and three in all, in the order the result gives them. Only http(s)\n * links count; anything else in the result is ignored.\n */\nexport function collectSourceUrls(result: unknown): string[] {\n const urls: string[] = [];\n const hosts = new Set<string>();\n const visit = ({ value, depth }: { value: unknown; depth: number }): void => {\n if (urls.length >= MAX_SOURCE_URLS || depth > MAX_SOURCE_DEPTH || value === null) return;\n if (Array.isArray(value)) {\n for (const entry of value) visit({ value: entry, depth: depth + 1 });\n return;\n }\n if (typeof value !== 'object') return;\n const record = value as Record<string, unknown>;\n for (const key of SOURCE_URL_KEYS) {\n const candidate = record[key];\n if (typeof candidate !== 'string') continue;\n const host = pageTarget(candidate);\n if (host && !hosts.has(host)) {\n hosts.add(host);\n urls.push(candidate);\n }\n break;\n }\n for (const entry of Object.values(record)) {\n if (typeof entry === 'object') visit({ value: entry, depth: depth + 1 });\n }\n };\n visit({ value: parseResult(result), depth: 0 });\n return urls;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ const assetUrls = require("../lib/asset-urls.cjs");
|
|
|
10
10
|
const apiClient = require("./suggestions/data/api-client.cjs");
|
|
11
11
|
const assetTypeIcons = require("./suggestions/data/sources/asset-type-icons.cjs");
|
|
12
12
|
const useMemberAvatar = require("./use-member-avatar.cjs");
|
|
13
|
+
const useMentionAsset = require("./use-mention-asset.cjs");
|
|
13
14
|
const screenPoint = require("../../agent-runtime/src/screen-point.cjs");
|
|
14
15
|
const cnfast = require("cnfast");
|
|
15
16
|
const SPACES_MENTION_PATH = /\/dashboard\/spaces\/?\?/;
|
|
@@ -81,11 +82,62 @@ const ASSET_CHIP_ICONS = {
|
|
|
81
82
|
web_page: lucideReact.Globe2Icon,
|
|
82
83
|
browse_session: lucideReact.Globe2Icon
|
|
83
84
|
};
|
|
84
|
-
function assetChipIcon(assetType
|
|
85
|
-
if ((citation == null ? void 0 : citation.anchorType) === "file_line_range") return lucideReact.FileCodeIcon;
|
|
85
|
+
function assetChipIcon(assetType) {
|
|
86
86
|
return assetType && ASSET_CHIP_ICONS[assetType.toLowerCase()] || lucideReact.FileIcon;
|
|
87
87
|
}
|
|
88
|
+
function GitHubMarkIcon({ className }) {
|
|
89
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
+
"svg",
|
|
91
|
+
{
|
|
92
|
+
viewBox: "0 0 16 16",
|
|
93
|
+
fill: "currentColor",
|
|
94
|
+
"aria-hidden": "true",
|
|
95
|
+
className,
|
|
96
|
+
"data-chip-icon": "github",
|
|
97
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" })
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const SESSION_ANCHORS = /* @__PURE__ */ new Set([
|
|
102
|
+
"msg",
|
|
103
|
+
"msg_range",
|
|
104
|
+
"msg_block",
|
|
105
|
+
"msg_section",
|
|
106
|
+
"msg_text",
|
|
107
|
+
"tool_call"
|
|
108
|
+
]);
|
|
109
|
+
function isSessionLink(assetType, citation) {
|
|
110
|
+
return (assetType == null ? void 0 : assetType.toLowerCase()) === "session" || citation !== void 0 && SESSION_ANCHORS.has(citation.anchorType);
|
|
111
|
+
}
|
|
112
|
+
const PLACE_FITS_CHARS = 20;
|
|
113
|
+
function splitFileLines(label) {
|
|
114
|
+
const colon = label.lastIndexOf(":");
|
|
115
|
+
return colon > 0 ? { file: label.slice(0, colon), lines: label.slice(colon) } : { file: label, lines: "" };
|
|
116
|
+
}
|
|
117
|
+
function restatesPlace(name, citation) {
|
|
118
|
+
const said = name.trim().toLowerCase();
|
|
119
|
+
const label = citation.label.toLowerCase();
|
|
120
|
+
return said === label || said === citation.description.toLowerCase() || said.endsWith(label);
|
|
121
|
+
}
|
|
122
|
+
function informativeLabel({
|
|
123
|
+
label,
|
|
124
|
+
shown,
|
|
125
|
+
citation
|
|
126
|
+
}) {
|
|
127
|
+
const trimmed = label.trim();
|
|
128
|
+
if (!trimmed || !SPEAKABLE.test(trimmed)) return null;
|
|
129
|
+
if (PLACEHOLDER_LABELS.has(trimmed.toLowerCase())) return null;
|
|
130
|
+
if (citation && restatesPlace(trimmed, citation)) return null;
|
|
131
|
+
const shownWords = new Set(
|
|
132
|
+
[...shown, citation == null ? void 0 : citation.description].flatMap((text) => text ? wordsOf(text) : [])
|
|
133
|
+
);
|
|
134
|
+
return wordsOf(trimmed).every((word) => shownWords.has(word)) ? null : trimmed;
|
|
135
|
+
}
|
|
136
|
+
function wordsOf(text) {
|
|
137
|
+
return text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
|
|
138
|
+
}
|
|
88
139
|
const SPEAKABLE = /[\p{L}\p{N}]/u;
|
|
140
|
+
const PLACEHOLDER_LABELS = /* @__PURE__ */ new Set(["citation", "source", "link", "here"]);
|
|
89
141
|
function decodeAssetLink(url, decode) {
|
|
90
142
|
try {
|
|
91
143
|
return decode(url);
|
|
@@ -97,9 +149,15 @@ function personEmailForMention(parsed) {
|
|
|
97
149
|
if (parsed.type !== "person") return void 0;
|
|
98
150
|
return parsed.email || (parsed.id.includes("@") ? parsed.id : void 0);
|
|
99
151
|
}
|
|
152
|
+
function textOf(node) {
|
|
153
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
154
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
155
|
+
if (react.isValidElement(node)) return textOf(node.props.children);
|
|
156
|
+
return "";
|
|
157
|
+
}
|
|
100
158
|
const MentionLink = ({ href, children, interactive = true }) => {
|
|
101
159
|
if (href && (href.startsWith("mention://") || isSpacesMentionUrl(href))) {
|
|
102
|
-
const name =
|
|
160
|
+
const name = textOf(children).trim().replace(/^@/, "");
|
|
103
161
|
const parsed = parseMentionUrl(href);
|
|
104
162
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
105
163
|
MentionChip,
|
|
@@ -124,6 +182,9 @@ const MentionLink = ({ href, children, interactive = true }) => {
|
|
|
124
182
|
}
|
|
125
183
|
return /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children });
|
|
126
184
|
};
|
|
185
|
+
const CHIP_PILL_CLASS = "not-prose box-border inline-flex h-5 items-center gap-1.5 whitespace-nowrap rounded-md border border-border bg-muted px-1 py-0.5 align-middle font-normal leading-none text-foreground no-underline";
|
|
186
|
+
const CHIP_LINK_CLASS = "cursor-pointer transition-colors hover:bg-accent hover:text-accent-foreground hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1";
|
|
187
|
+
const CHIP_ICON_CLASS = "size-4 shrink-0";
|
|
127
188
|
const ScreenPointChip = ({ href, children }) => {
|
|
128
189
|
const parsed = screenPoint.parseScreenPointHref(href);
|
|
129
190
|
if (!parsed.ok) {
|
|
@@ -133,14 +194,14 @@ const ScreenPointChip = ({ href, children }) => {
|
|
|
133
194
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
134
195
|
"span",
|
|
135
196
|
{
|
|
136
|
-
className: "
|
|
197
|
+
className: cnfast.cn(CHIP_PILL_CLASS, "max-w-[260px]"),
|
|
137
198
|
title: description,
|
|
138
199
|
"aria-label": description,
|
|
139
200
|
"data-screen-point": "valid",
|
|
140
201
|
children: [
|
|
141
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CrosshairIcon, { className:
|
|
142
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-[180px] overflow-hidden text-ellipsis", children }),
|
|
143
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "
|
|
202
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CrosshairIcon, { className: CHIP_ICON_CLASS, "aria-hidden": "true" }),
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 max-w-[180px] overflow-hidden text-ellipsis", children }),
|
|
204
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
144
205
|
parsed.point.x,
|
|
145
206
|
", ",
|
|
146
207
|
parsed.point.y
|
|
@@ -164,8 +225,21 @@ const MentionChip = ({
|
|
|
164
225
|
const memberAvatarUrl = useMemberAvatar.useMemberAvatarUrl(personEmail);
|
|
165
226
|
const [erroredAvatarUrl, setErroredAvatarUrl] = react.useState();
|
|
166
227
|
const excerpt = sourceHref ? readSourceExcerpt(sourceHref) : null;
|
|
167
|
-
const
|
|
168
|
-
const
|
|
228
|
+
const repositoryFile = (citation == null ? void 0 : citation.anchorType) === "file_line_range" ? { ...splitFileLines(citation.label), label: citation.label } : null;
|
|
229
|
+
const asset = useMentionAsset.useMentionAsset(
|
|
230
|
+
type === "asset" && (assetIds == null ? void 0 : assetIds.length) === 1 && !repositoryFile && !isSessionLink(assetType, citation) ? assetIds[0] : void 0
|
|
231
|
+
);
|
|
232
|
+
const assetTitle = (asset == null ? void 0 : asset.title) || null;
|
|
233
|
+
const chipName = (repositoryFile == null ? void 0 : repositoryFile.label) ?? assetTitle ?? name;
|
|
234
|
+
const placeLabel = citation && !repositoryFile && !restatesPlace(chipName, citation) ? citation.label : null;
|
|
235
|
+
const tooltip = citation || excerpt ? tooltipText({
|
|
236
|
+
lines: [
|
|
237
|
+
informativeLabel({ label: name, shown: [chipName, assetTitle], citation }),
|
|
238
|
+
repositoryFile ? assetTitle : null,
|
|
239
|
+
repositoryFile || !excerpt || ((placeLabel == null ? void 0 : placeLabel.length) ?? 0) > PLACE_FITS_CHARS ? citation == null ? void 0 : citation.description : null
|
|
240
|
+
],
|
|
241
|
+
excerpt
|
|
242
|
+
}) : null;
|
|
169
243
|
const assetRootHref = type === "asset" && (assetIds == null ? void 0 : assetIds.length) ? assetUrls.createOlympusAssetUrl({
|
|
170
244
|
appUrl: auth == null ? void 0 : auth.appUrl,
|
|
171
245
|
backendUrl: auth == null ? void 0 : auth.backendUrl,
|
|
@@ -185,51 +259,71 @@ const MentionChip = ({
|
|
|
185
259
|
return assetRootHref;
|
|
186
260
|
}
|
|
187
261
|
})();
|
|
188
|
-
const className = cnfast.cn(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
anchorLabel && "max-w-[340px]",
|
|
192
|
-
href && "cursor-pointer transition-colors hover:border-slate-400 hover:bg-slate-50 hover:text-slate-800 hover:no-underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1"
|
|
193
|
-
);
|
|
194
|
-
const AssetIcon = assetChipIcon(assetType, citation);
|
|
262
|
+
const className = cnfast.cn(CHIP_PILL_CLASS, "max-w-[275px]", href && CHIP_LINK_CLASS);
|
|
263
|
+
const chipThumbnailUrl = repositoryFile ? void 0 : (asset == null ? void 0 : asset.assetType) && assetTypeIcons.assetTypeToThumb(asset.assetType) || thumbnailUrl;
|
|
264
|
+
const AssetIcon = assetChipIcon((asset == null ? void 0 : asset.assetType) || assetType);
|
|
195
265
|
const contents = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
196
|
-
|
|
266
|
+
repositoryFile ? /* @__PURE__ */ jsxRuntime.jsx(GitHubMarkIcon, { className: CHIP_ICON_CLASS }) : chipThumbnailUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
197
267
|
"img",
|
|
198
268
|
{
|
|
199
|
-
src:
|
|
269
|
+
src: chipThumbnailUrl,
|
|
200
270
|
alt: "",
|
|
201
|
-
className:
|
|
271
|
+
className: CHIP_ICON_CLASS,
|
|
202
272
|
draggable: false
|
|
203
273
|
}
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
!thumbnailUrl && type === "person" && (memberAvatarUrl && erroredAvatarUrl !== memberAvatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
274
|
+
) : type === "asset" || type === "folder" ? (
|
|
275
|
+
// A host that bundles no asset-type SVGs (computer apps, most SDK
|
|
276
|
+
// apps) still gets the type's icon.
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsx(AssetIcon, { className: CHIP_ICON_CLASS, "aria-hidden": "true" })
|
|
278
|
+
) : type === "webpage" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Globe2Icon, { className: CHIP_ICON_CLASS, "aria-hidden": "true" }) : type === "person" ? memberAvatarUrl && erroredAvatarUrl !== memberAvatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
210
279
|
"img",
|
|
211
280
|
{
|
|
212
281
|
src: memberAvatarUrl,
|
|
213
282
|
alt: "",
|
|
214
|
-
className:
|
|
283
|
+
className: cnfast.cn(CHIP_ICON_CLASS, "rounded-full object-cover"),
|
|
215
284
|
draggable: false,
|
|
216
285
|
onError: () => setErroredAvatarUrl(memberAvatarUrl)
|
|
217
286
|
}
|
|
218
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserIcon, { className:
|
|
219
|
-
/* @__PURE__ */ jsxRuntime.
|
|
220
|
-
|
|
287
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserIcon, { className: CHIP_ICON_CLASS, "aria-hidden": "true" }) : null,
|
|
288
|
+
repositoryFile ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
289
|
+
"span",
|
|
290
|
+
{
|
|
291
|
+
className: "flex min-w-0 items-center",
|
|
292
|
+
"data-citation-anchor": "file_line_range",
|
|
293
|
+
children: [
|
|
294
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis", children: repositoryFile.file }),
|
|
295
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-muted-foreground", children: repositoryFile.lines })
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
299
|
+
"span",
|
|
300
|
+
{
|
|
301
|
+
className: cnfast.cn(
|
|
302
|
+
"max-w-[180px] overflow-hidden text-ellipsis",
|
|
303
|
+
// A long place may shorten the name, never make it vanish.
|
|
304
|
+
placeLabel && "min-w-8"
|
|
305
|
+
),
|
|
306
|
+
children: chipName
|
|
307
|
+
}
|
|
308
|
+
),
|
|
309
|
+
citation && placeLabel && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
221
310
|
" ",
|
|
222
|
-
/* @__PURE__ */ jsxRuntime.
|
|
311
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
223
312
|
"span",
|
|
224
313
|
{
|
|
225
|
-
className: "
|
|
314
|
+
className: "flex min-w-0 items-center text-xs text-muted-foreground",
|
|
226
315
|
"data-citation-anchor": citation.anchorType,
|
|
227
|
-
children:
|
|
316
|
+
children: [
|
|
317
|
+
"[",
|
|
318
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis", children: placeLabel }),
|
|
319
|
+
"]"
|
|
320
|
+
]
|
|
228
321
|
}
|
|
229
322
|
)
|
|
230
323
|
] })
|
|
231
324
|
] });
|
|
232
325
|
if (href && interactive) {
|
|
326
|
+
const speakablePlace = citation && SPEAKABLE.test(citation.description);
|
|
233
327
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
234
328
|
"a",
|
|
235
329
|
{
|
|
@@ -237,10 +331,10 @@ const MentionChip = ({
|
|
|
237
331
|
target: "_blank",
|
|
238
332
|
rel: "noopener noreferrer",
|
|
239
333
|
className,
|
|
240
|
-
"aria-label":
|
|
241
|
-
title: tooltip ?? `Open ${
|
|
334
|
+
"aria-label": repositoryFile && citation ? `Open ${citation.description} in Spaces` : placeLabel && citation && speakablePlace ? `Open ${chipName} at ${citation.description} in Spaces` : `Open ${chipName} in Spaces`,
|
|
335
|
+
title: tooltip ?? `Open ${chipName} in Spaces`,
|
|
242
336
|
"data-excerpt": excerpt ?? void 0,
|
|
243
|
-
"data-mention-name": name,
|
|
337
|
+
"data-mention-name": repositoryFile ? assetTitle ?? name : chipName,
|
|
244
338
|
children: contents
|
|
245
339
|
}
|
|
246
340
|
);
|
|
@@ -255,6 +349,18 @@ const MentionChip = ({
|
|
|
255
349
|
}
|
|
256
350
|
);
|
|
257
351
|
};
|
|
352
|
+
function tooltipText({
|
|
353
|
+
lines,
|
|
354
|
+
excerpt
|
|
355
|
+
}) {
|
|
356
|
+
const kept = [];
|
|
357
|
+
for (const line of lines) {
|
|
358
|
+
const trimmed = line == null ? void 0 : line.trim();
|
|
359
|
+
if (trimmed && !kept.includes(trimmed)) kept.push(trimmed);
|
|
360
|
+
}
|
|
361
|
+
if (excerpt) kept.push(kept.length ? `“${excerpt}”` : excerpt);
|
|
362
|
+
return kept.length ? kept.join("\n") : null;
|
|
363
|
+
}
|
|
258
364
|
function readSourceExcerpt(href) {
|
|
259
365
|
var _a;
|
|
260
366
|
try {
|
|
@@ -400,6 +506,9 @@ function mentionsToPlainText(text) {
|
|
|
400
506
|
return `@${name || parseMentionUrl(url).name}`;
|
|
401
507
|
});
|
|
402
508
|
}
|
|
509
|
+
exports.CHIP_ICON_CLASS = CHIP_ICON_CLASS;
|
|
510
|
+
exports.CHIP_LINK_CLASS = CHIP_LINK_CLASS;
|
|
511
|
+
exports.CHIP_PILL_CLASS = CHIP_PILL_CLASS;
|
|
403
512
|
exports.MentionChip = MentionChip;
|
|
404
513
|
exports.MentionLink = MentionLink;
|
|
405
514
|
exports.ScreenPointChip = ScreenPointChip;
|