@alpaca-editor/core 1.0.4104 → 1.0.4105
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/editor/MainLayout.js +1 -1
- package/dist/editor/MainLayout.js.map +1 -1
- package/dist/editor/Terminal.js +2 -2
- package/dist/editor/Terminal.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.js +5 -3
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +9 -1
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +4 -2
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/client/EditorShell.js +2 -0
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/control-center/IndexOverview.js +3 -2
- package/dist/editor/control-center/IndexOverview.js.map +1 -1
- package/dist/editor/control-center/WebSocketMessages.js +3 -3
- package/dist/editor/control-center/WebSocketMessages.js.map +1 -1
- package/dist/editor/media-selector/MediaFolderBrowser.js +2 -2
- package/dist/editor/media-selector/MediaFolderBrowser.js.map +1 -1
- package/dist/editor/menubar/ActiveUsers.js +3 -2
- package/dist/editor/menubar/ActiveUsers.js.map +1 -1
- package/dist/editor/reviews/Comments.js +96 -35
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/sidebar/Completions.js +2 -1
- package/dist/editor/sidebar/Completions.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +2 -1
- package/dist/editor/ui/Icons.js +2 -2
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/editor/ui/SimpleTable.js +1 -1
- package/dist/editor/ui/SimpleTable.js.map +1 -1
- package/dist/editor/utils.d.ts +12 -1
- package/dist/editor/utils.js +60 -12
- package/dist/editor/utils.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/package.json +1 -1
- package/src/editor/MainLayout.tsx +1 -1
- package/src/editor/Terminal.tsx +2 -2
- package/src/editor/ai/AgentTerminal.tsx +8 -20
- package/src/editor/ai/Agents.tsx +14 -2
- package/src/editor/ai/AiResponseMessage.tsx +7 -5
- package/src/editor/client/EditorShell.tsx +2 -0
- package/src/editor/control-center/IndexOverview.tsx +3 -2
- package/src/editor/control-center/WebSocketMessages.tsx +3 -5
- package/src/editor/media-selector/MediaFolderBrowser.tsx +2 -2
- package/src/editor/menubar/ActiveUsers.tsx +4 -3
- package/src/editor/reviews/Comments.tsx +123 -38
- package/src/editor/sidebar/Completions.tsx +2 -1
- package/src/editor/ui/Icons.tsx +3 -0
- package/src/editor/ui/SimpleTable.tsx +2 -2
- package/src/editor/utils.ts +73 -15
- package/src/revision.ts +2 -2
package/dist/revision.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.0.
|
|
2
|
-
export declare const buildDate = "2025-09-23
|
|
1
|
+
export declare const version = "1.0.4105";
|
|
2
|
+
export declare const buildDate = "2025-09-23 15:04:32";
|
package/dist/revision.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-09-23
|
|
1
|
+
export const version = "1.0.4105";
|
|
2
|
+
export const buildDate = "2025-09-23 15:04:32";
|
|
3
3
|
//# sourceMappingURL=revision.js.map
|
package/package.json
CHANGED
|
@@ -84,7 +84,7 @@ export default function MainLayout(props: MainLayoutProps) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
return (
|
|
87
|
-
<div className={classNames("flex font-
|
|
87
|
+
<div className={classNames("flex font-normal select-none", className)}>
|
|
88
88
|
<div className="flex flex-1">
|
|
89
89
|
{!props.view.hideViewSelector && <LeftToolbar />}
|
|
90
90
|
<div className="flex flex-1 flex-col">
|
package/src/editor/Terminal.tsx
CHANGED
|
@@ -175,10 +175,10 @@ export const Terminal = forwardRef<
|
|
|
175
175
|
}, [messages, response]);
|
|
176
176
|
|
|
177
177
|
const responseBoxClasses =
|
|
178
|
-
"text-xs self-stretch text-
|
|
178
|
+
"text-xs self-stretch text-dark p-2 rounded border border-theme-secondary bg-theme-secondary-light min-h-8 flex flex-col justify-end";
|
|
179
179
|
const getClasses = (m: Message) => {
|
|
180
180
|
if (m.type === "response") return responseBoxClasses;
|
|
181
|
-
return "text-xs text-
|
|
181
|
+
return "text-xs text-dark bg-indigo-100 border border-indigo-300 p-2 rounded prompt";
|
|
182
182
|
};
|
|
183
183
|
|
|
184
184
|
// Expose the submit function via the ref.
|
|
@@ -5,22 +5,7 @@ import React, {
|
|
|
5
5
|
useCallback,
|
|
6
6
|
useLayoutEffect,
|
|
7
7
|
} from "react";
|
|
8
|
-
import {
|
|
9
|
-
Send,
|
|
10
|
-
Bot,
|
|
11
|
-
AlertCircle,
|
|
12
|
-
Loader2,
|
|
13
|
-
User,
|
|
14
|
-
X,
|
|
15
|
-
FileText,
|
|
16
|
-
Puzzle,
|
|
17
|
-
Type,
|
|
18
|
-
Plus,
|
|
19
|
-
MessageSquare,
|
|
20
|
-
Wand2,
|
|
21
|
-
Square,
|
|
22
|
-
ChevronDown,
|
|
23
|
-
} from "lucide-react";
|
|
8
|
+
import { Send, AlertCircle, Loader2, User, Wand2, Square } from "lucide-react";
|
|
24
9
|
import { DancingDots } from "./DancingDots";
|
|
25
10
|
import {
|
|
26
11
|
AgentChatMessage,
|
|
@@ -52,6 +37,8 @@ import {
|
|
|
52
37
|
PopoverContent,
|
|
53
38
|
PopoverTrigger,
|
|
54
39
|
} from "../../components/ui/popover";
|
|
40
|
+
import { SecretAgentIcon } from "../ui/Icons";
|
|
41
|
+
import { formatTime, formatDateTime } from "../utils";
|
|
55
42
|
|
|
56
43
|
// Simple user message component
|
|
57
44
|
const UserMessage = ({ message }: { message: AgentChatMessage }) => {
|
|
@@ -62,10 +49,10 @@ const UserMessage = ({ message }: { message: AgentChatMessage }) => {
|
|
|
62
49
|
</div>
|
|
63
50
|
<div className="min-w-0 flex-1 select-text">
|
|
64
51
|
<div className="mb-1 flex items-center gap-2">
|
|
65
|
-
<span className="text-
|
|
52
|
+
<span className="text-xs font-medium text-gray-900">You</span>
|
|
66
53
|
{message.createdDate && (
|
|
67
54
|
<span className="text-xs text-gray-400">
|
|
68
|
-
{new Date(message.createdDate)
|
|
55
|
+
{formatTime(new Date(message.createdDate))}
|
|
69
56
|
</span>
|
|
70
57
|
)}
|
|
71
58
|
</div>
|
|
@@ -2233,9 +2220,10 @@ export function AgentTerminal({
|
|
|
2233
2220
|
{messages.length === 0 && !error && (
|
|
2234
2221
|
<div className="flex h-full items-center justify-center p-8">
|
|
2235
2222
|
<div className="text-center">
|
|
2236
|
-
<
|
|
2237
|
-
|
|
2223
|
+
<SecretAgentIcon
|
|
2224
|
+
size={48}
|
|
2238
2225
|
strokeWidth={1}
|
|
2226
|
+
className="mx-auto mb-4 text-gray-400"
|
|
2239
2227
|
/>
|
|
2240
2228
|
<h3 className="mb-2 text-lg font-medium text-gray-900">
|
|
2241
2229
|
Start a conversation
|
package/src/editor/ai/Agents.tsx
CHANGED
|
@@ -502,7 +502,6 @@ export function Agents({ closeButton }: { closeButton?: React.ReactNode }) {
|
|
|
502
502
|
return (
|
|
503
503
|
<div className="flex h-full items-center justify-center">
|
|
504
504
|
<div className="w-72">
|
|
505
|
-
|
|
506
505
|
{loadingProfiles ? (
|
|
507
506
|
<div className="text-center text-xs text-gray-500">
|
|
508
507
|
Loading profiles...
|
|
@@ -670,7 +669,20 @@ export function Agents({ closeButton }: { closeButton?: React.ReactNode }) {
|
|
|
670
669
|
{agent.name}
|
|
671
670
|
</div>
|
|
672
671
|
<div className="text-xs text-gray-400">
|
|
673
|
-
{
|
|
672
|
+
{(() => {
|
|
673
|
+
try {
|
|
674
|
+
const {
|
|
675
|
+
formatDateTime,
|
|
676
|
+
} = require("../utils");
|
|
677
|
+
return formatDateTime(
|
|
678
|
+
new Date(agent.updatedDate),
|
|
679
|
+
);
|
|
680
|
+
} catch {
|
|
681
|
+
return new Date(
|
|
682
|
+
agent.updatedDate,
|
|
683
|
+
).toLocaleString();
|
|
684
|
+
}
|
|
685
|
+
})()}
|
|
674
686
|
</div>
|
|
675
687
|
</div>
|
|
676
688
|
<SimpleIconButton
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState, useEffect, useMemo } from "react";
|
|
2
|
+
import { formatTime } from "../utils";
|
|
2
3
|
|
|
3
4
|
import { useEditContext } from "../client/editContext";
|
|
4
5
|
import { EditOperation } from "../../types";
|
|
5
6
|
import { Message, ToolCall } from "./types";
|
|
6
7
|
import { ToolCallDisplay } from "./ToolCallDisplay";
|
|
7
8
|
|
|
8
|
-
import { X
|
|
9
|
+
import { X } from "lucide-react";
|
|
9
10
|
import { Button } from "../../components/ui/button";
|
|
10
11
|
import { Checkbox } from "../../components/ui/checkbox";
|
|
12
|
+
import { SecretAgentIcon } from "../ui/Icons";
|
|
11
13
|
|
|
12
14
|
type QuickAction = {
|
|
13
15
|
id?: string;
|
|
@@ -464,15 +466,15 @@ export function AiResponseMessage({
|
|
|
464
466
|
return (
|
|
465
467
|
<div className="flex gap-3 p-4" data-testid="agent-message">
|
|
466
468
|
<div className="flex-shrink-0">
|
|
467
|
-
<
|
|
469
|
+
<SecretAgentIcon size={24} strokeWidth={1} className="text-gray-2" />
|
|
468
470
|
</div>
|
|
469
471
|
<div className="min-w-0 flex-1 select-text">
|
|
470
472
|
<div className="mb-1 flex items-center gap-2">
|
|
471
|
-
<span className="text-
|
|
473
|
+
<span className="text-dark text-xs font-medium">Agent</span>
|
|
472
474
|
|
|
473
475
|
{lastMessage && lastMessage.createdDate && (
|
|
474
476
|
<span className="text-xs text-gray-400">
|
|
475
|
-
{new Date(lastMessage.createdDate)
|
|
477
|
+
{formatTime(new Date(lastMessage.createdDate))}
|
|
476
478
|
</span>
|
|
477
479
|
)}
|
|
478
480
|
</div>
|
|
@@ -2157,6 +2157,7 @@ export function EditorShell({
|
|
|
2157
2157
|
revision,
|
|
2158
2158
|
comments,
|
|
2159
2159
|
setComments,
|
|
2160
|
+
availableCommentTags,
|
|
2160
2161
|
selectedComment,
|
|
2161
2162
|
setSelectedComment,
|
|
2162
2163
|
loadComments,
|
|
@@ -2172,6 +2173,7 @@ export function EditorShell({
|
|
|
2172
2173
|
setShowSuggestedEdits,
|
|
2173
2174
|
showSuggestedEditsDiff,
|
|
2174
2175
|
setShowSuggestedEditsDiff,
|
|
2176
|
+
showComments,
|
|
2175
2177
|
showResolvedComments,
|
|
2176
2178
|
setShowResolvedComments,
|
|
2177
2179
|
showComponentNavigator,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "lucide-react";
|
|
10
10
|
|
|
11
11
|
import { classNames } from "primereact/utils";
|
|
12
|
+
import { formatDateOnly, formatDateTime } from "../utils";
|
|
12
13
|
import {
|
|
13
14
|
IndexStatus,
|
|
14
15
|
StagingStatus,
|
|
@@ -527,7 +528,7 @@ export function IndexOverview() {
|
|
|
527
528
|
</div>
|
|
528
529
|
<div className="text-xs text-gray-500">
|
|
529
530
|
{batch.created
|
|
530
|
-
? new Date(batch.created)
|
|
531
|
+
? formatDateOnly(new Date(batch.created))
|
|
531
532
|
: "Unknown"}
|
|
532
533
|
</div>
|
|
533
534
|
</div>
|
|
@@ -584,7 +585,7 @@ export function IndexOverview() {
|
|
|
584
585
|
)}
|
|
585
586
|
</div>
|
|
586
587
|
<div className="ml-2 shrink-0 text-xs text-gray-500">
|
|
587
|
-
{new Date(it.created)
|
|
588
|
+
{formatDateTime(new Date(it.created))}
|
|
588
589
|
</div>
|
|
589
590
|
</div>
|
|
590
591
|
))}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect, useRef } from "react";
|
|
2
|
+
import { formatTime } from "../utils";
|
|
2
3
|
import { useEditContext } from "../client/editContext";
|
|
3
4
|
|
|
4
5
|
export function WebSocketMessages() {
|
|
@@ -34,11 +35,8 @@ export function WebSocketMessages() {
|
|
|
34
35
|
|
|
35
36
|
const formatTimestamp = (isoString: string) => {
|
|
36
37
|
const date = new Date(isoString);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"." +
|
|
40
|
-
date.getMilliseconds().toString().padStart(3, "0")
|
|
41
|
-
);
|
|
38
|
+
const base = formatTime(date);
|
|
39
|
+
return base + "." + date.getMilliseconds().toString().padStart(3, "0");
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
const getMessageTypeColor = (type: string) => {
|
|
@@ -195,7 +195,7 @@ export function MediaFolderBrowser({
|
|
|
195
195
|
/>
|
|
196
196
|
</div>
|
|
197
197
|
<div className="min-w-0 flex-1">
|
|
198
|
-
<div className="truncate text-
|
|
198
|
+
<div className="text-dark truncate text-xs font-medium">
|
|
199
199
|
{t.name}
|
|
200
200
|
</div>
|
|
201
201
|
<div className="mt-1 text-xs text-gray-500">Media File</div>
|
|
@@ -305,7 +305,7 @@ export function MediaFolderBrowser({
|
|
|
305
305
|
{/* Selected Item Info */}
|
|
306
306
|
{selectedImage && (
|
|
307
307
|
<div className="border-t bg-gray-50 p-3">
|
|
308
|
-
<div className="truncate text-
|
|
308
|
+
<div className="text-dark truncate text-xs font-medium">
|
|
309
309
|
Selected: {selectedImage.name}
|
|
310
310
|
</div>
|
|
311
311
|
<div className="mt-1 text-xs text-gray-500">
|
|
@@ -9,6 +9,7 @@ import { useEffect, useState } from "react";
|
|
|
9
9
|
import { getItemVisitors, ItemVisitor } from "../services/editService";
|
|
10
10
|
import { VerticalDotsIcon } from "../ui/Icons";
|
|
11
11
|
import { AboutDialog } from "../client/AboutDialog";
|
|
12
|
+
import { formatDateOnly } from "../utils";
|
|
12
13
|
|
|
13
14
|
type UserListItem = {
|
|
14
15
|
type: "active" | "visitor";
|
|
@@ -258,7 +259,7 @@ export function ActiveUsers() {
|
|
|
258
259
|
/>
|
|
259
260
|
</div>
|
|
260
261
|
<div className="min-w-0 flex-1">
|
|
261
|
-
<div className="text-
|
|
262
|
+
<div className="text-dark text-xs font-medium">About</div>
|
|
262
263
|
</div>
|
|
263
264
|
</div>
|
|
264
265
|
<div
|
|
@@ -272,7 +273,7 @@ export function ActiveUsers() {
|
|
|
272
273
|
/>
|
|
273
274
|
</div>
|
|
274
275
|
<div className="min-w-0 flex-1">
|
|
275
|
-
<div className="text-
|
|
276
|
+
<div className="text-dark text-xs font-medium">Log Out</div>
|
|
276
277
|
</div>
|
|
277
278
|
</div>
|
|
278
279
|
</div>
|
|
@@ -296,5 +297,5 @@ function formatTimeAgo(date: Date): string {
|
|
|
296
297
|
if (diffInSeconds < 604800)
|
|
297
298
|
return `${Math.floor(diffInSeconds / 86400)}d ago`;
|
|
298
299
|
|
|
299
|
-
return date
|
|
300
|
+
return formatDateOnly(date);
|
|
300
301
|
}
|
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
Tags,
|
|
23
23
|
Lightbulb,
|
|
24
24
|
} from "lucide-react";
|
|
25
|
+
import { getChildren } from "../services/contentService";
|
|
26
|
+
import { getComments as getCommentsApi } from "../services/reviewsService";
|
|
25
27
|
|
|
26
28
|
// Define a union type for feedback items:
|
|
27
29
|
export type FeedbackItem = CommentType | SuggestedEdit;
|
|
@@ -56,52 +58,135 @@ export function Comments() {
|
|
|
56
58
|
const availableTags = editContext?.availableCommentTags || [];
|
|
57
59
|
|
|
58
60
|
useEffect(() => {
|
|
59
|
-
|
|
60
|
-
// for instance from your editContext)
|
|
61
|
-
const comments: CommentType[] = editContext?.comments || [];
|
|
62
|
-
const suggestedEdits: SuggestedEdit[] = editContext?.suggestedEdits || [];
|
|
61
|
+
let cancelled = false;
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
: suggestedEdits;
|
|
63
|
+
const load = async () => {
|
|
64
|
+
// Base lists from context
|
|
65
|
+
const mainComments: CommentType[] = editContext?.comments || [];
|
|
66
|
+
const suggestedEdits: SuggestedEdit[] = editContext?.suggestedEdits || [];
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
// Filter out applied suggestions if hideAppliedSuggestions is true
|
|
69
|
+
const filteredSuggestedEdits = hideAppliedSuggestions
|
|
70
|
+
? suggestedEdits.filter((edit) => edit.status !== "applied")
|
|
71
|
+
: suggestedEdits;
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
(editContext?.selection && editContext.selection[0]) ||
|
|
75
|
-
editContext?.currentItemDescriptor?.id ||
|
|
76
|
-
undefined;
|
|
73
|
+
// Start with main page comments and suggestions
|
|
74
|
+
let allComments: CommentType[] = [...mainComments];
|
|
77
75
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
// If including children, fetch comments for descendant pages and merge
|
|
77
|
+
const basePageId = editContext?.currentItemDescriptor?.id;
|
|
78
|
+
const baseLanguage = editContext?.currentItemDescriptor?.language;
|
|
79
|
+
const baseVersion = editContext?.currentItemDescriptor?.version;
|
|
80
|
+
|
|
81
|
+
if (scope === "all" && basePageId && baseLanguage && baseVersion) {
|
|
82
|
+
try {
|
|
83
|
+
const sessionId = editContext?.sessionId || "";
|
|
84
|
+
|
|
85
|
+
// BFS to collect all descendant nodes
|
|
86
|
+
const queue: string[] = [basePageId];
|
|
87
|
+
const visited = new Set<string>();
|
|
88
|
+
const descendantPages: {
|
|
89
|
+
id: string;
|
|
90
|
+
language: string;
|
|
91
|
+
version: number;
|
|
92
|
+
hasChildren: boolean;
|
|
93
|
+
}[] = [];
|
|
94
|
+
|
|
95
|
+
while (queue.length > 0) {
|
|
96
|
+
const parentId = queue.shift()!;
|
|
97
|
+
if (visited.has(parentId)) continue;
|
|
98
|
+
visited.add(parentId);
|
|
99
|
+
|
|
100
|
+
const children = await getChildren(
|
|
101
|
+
parentId,
|
|
102
|
+
sessionId,
|
|
103
|
+
[],
|
|
104
|
+
false,
|
|
105
|
+
baseLanguage,
|
|
106
|
+
undefined,
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
for (const child of children) {
|
|
110
|
+
// Enqueue for deeper traversal when it has children
|
|
111
|
+
if (child.hasChildren) queue.push(child.id);
|
|
112
|
+
// Only pages (hasLayout) contribute comments
|
|
113
|
+
if (child.hasLayout) {
|
|
114
|
+
descendantPages.push({
|
|
115
|
+
id: child.id,
|
|
116
|
+
language: child.language,
|
|
117
|
+
version: child.version,
|
|
118
|
+
hasChildren: child.hasChildren,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Fetch comments for all descendant pages in parallel
|
|
125
|
+
const results = await Promise.all(
|
|
126
|
+
descendantPages.map((p) =>
|
|
127
|
+
getCommentsApi(p.id, p.language, p.version),
|
|
128
|
+
),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const childComments = results
|
|
132
|
+
.map((r) => (r.data || []) as CommentType[])
|
|
133
|
+
.flat();
|
|
134
|
+
|
|
135
|
+
// Merge unique by id
|
|
136
|
+
const existingIds = new Set(allComments.map((c) => c.id));
|
|
137
|
+
for (const c of childComments) {
|
|
138
|
+
if (!existingIds.has(c.id)) {
|
|
139
|
+
allComments.push(c);
|
|
140
|
+
existingIds.add(c.id);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
} catch {
|
|
144
|
+
// Ignore child-loading errors to avoid blocking main list
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Combine with suggestions
|
|
149
|
+
let combined: FeedbackItem[] = [
|
|
150
|
+
...allComments,
|
|
151
|
+
...filteredSuggestedEdits,
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
// Apply scope filter for item-only: keep only items whose mainItemId is the current page
|
|
155
|
+
if (scope === "itemOnly" && basePageId) {
|
|
156
|
+
combined = combined.filter(
|
|
157
|
+
(item: any) => item.mainItemId === basePageId,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Apply tag filter to comments only (suggested edits do not have tags)
|
|
162
|
+
const tagFiltered = selectedTagsFilter.length
|
|
163
|
+
? combined.filter((item: any) => {
|
|
164
|
+
// Keep suggested edits
|
|
165
|
+
if ("oldValue" in item && "newValue" in item) return true;
|
|
166
|
+
const tags = (item.tags || "")
|
|
167
|
+
.split(",")
|
|
168
|
+
.map((t: string) => t.trim())
|
|
169
|
+
.filter(Boolean);
|
|
170
|
+
// OR logic: include if any selected tag matches
|
|
171
|
+
return selectedTagsFilter.some((t) => tags.includes(t));
|
|
172
|
+
})
|
|
81
173
|
: combined;
|
|
82
174
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// OR logic: include if any selected tag matches
|
|
93
|
-
return selectedTagsFilter.some((t) => tags.includes(t));
|
|
94
|
-
})
|
|
95
|
-
: scoped;
|
|
175
|
+
// Sort by creation date
|
|
176
|
+
tagFiltered.sort(
|
|
177
|
+
(a, b) =>
|
|
178
|
+
new Date(b.created || "").getTime() -
|
|
179
|
+
new Date(a.created || "").getTime(),
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
if (!cancelled) setFeedbackItems(tagFiltered);
|
|
183
|
+
};
|
|
96
184
|
|
|
97
|
-
|
|
98
|
-
tagFiltered.sort(
|
|
99
|
-
(a, b) =>
|
|
100
|
-
new Date(b.created || "").getTime() -
|
|
101
|
-
new Date(a.created || "").getTime(),
|
|
102
|
-
);
|
|
185
|
+
load();
|
|
103
186
|
|
|
104
|
-
|
|
187
|
+
return () => {
|
|
188
|
+
cancelled = true;
|
|
189
|
+
};
|
|
105
190
|
}, [editContext, hideAppliedSuggestions, scope, selectedTagsFilter]);
|
|
106
191
|
|
|
107
192
|
useEffect(() => {
|
|
@@ -4,6 +4,7 @@ import { Switch } from "../../components/ui/switch";
|
|
|
4
4
|
import { Button } from "../../components/ui/button";
|
|
5
5
|
import { Badge } from "../../components/ui/badge";
|
|
6
6
|
import { Loader2, RefreshCw, FileText } from "lucide-react";
|
|
7
|
+
import { formatTime } from "../utils";
|
|
7
8
|
|
|
8
9
|
import {
|
|
9
10
|
generatePageContext,
|
|
@@ -120,7 +121,7 @@ export function Completions() {
|
|
|
120
121
|
{pageContext.abstract}
|
|
121
122
|
</p>
|
|
122
123
|
<div className="text-xs text-gray-400">
|
|
123
|
-
Generated: {pageContext.lastGenerated
|
|
124
|
+
{`Generated: ${formatTime(pageContext.lastGenerated)}`}
|
|
124
125
|
</div>
|
|
125
126
|
</div>
|
|
126
127
|
) : (
|
package/src/editor/ui/Icons.tsx
CHANGED
|
@@ -891,10 +891,12 @@ export function SecretAgentIcon({
|
|
|
891
891
|
title,
|
|
892
892
|
strokeWidth = 1,
|
|
893
893
|
size = 20,
|
|
894
|
+
className,
|
|
894
895
|
}: {
|
|
895
896
|
title?: string;
|
|
896
897
|
strokeWidth?: number;
|
|
897
898
|
size?: number;
|
|
899
|
+
className?: string;
|
|
898
900
|
}) {
|
|
899
901
|
return (
|
|
900
902
|
<svg
|
|
@@ -909,6 +911,7 @@ export function SecretAgentIcon({
|
|
|
909
911
|
strokeLinejoin="round"
|
|
910
912
|
role="img"
|
|
911
913
|
aria-label={title}
|
|
914
|
+
className={className}
|
|
912
915
|
>
|
|
913
916
|
<path d="M3 10h18" />
|
|
914
917
|
<path d="M7 10l2-5h6l2 5" />
|
|
@@ -23,10 +23,10 @@ export function SimpleTable<T>({
|
|
|
23
23
|
}) {
|
|
24
24
|
return (
|
|
25
25
|
<table className="text-surface min-w-full table-auto text-left text-xs font-light">
|
|
26
|
-
<thead className="border-b border-neutral-200
|
|
26
|
+
<thead className="border-b border-neutral-200">
|
|
27
27
|
<tr>
|
|
28
28
|
{columns.map((col, index) => (
|
|
29
|
-
<th key={index} className="px-1.5 py-1.5">
|
|
29
|
+
<th key={index} className="px-1.5 py-1.5 font-medium">
|
|
30
30
|
{col.header}
|
|
31
31
|
</th>
|
|
32
32
|
))}
|
package/src/editor/utils.ts
CHANGED
|
@@ -504,23 +504,81 @@ export function normalizeGuid(id: string) {
|
|
|
504
504
|
return "{" + id + "}";
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
507
|
+
function getLocale() {
|
|
508
|
+
try {
|
|
509
|
+
if (typeof navigator !== "undefined" && navigator.language)
|
|
510
|
+
return navigator.language;
|
|
511
|
+
} catch {}
|
|
512
|
+
return "en";
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function getUserTimeZone() {
|
|
516
|
+
try {
|
|
517
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
518
|
+
return tz || "UTC";
|
|
519
|
+
} catch {
|
|
520
|
+
return "UTC";
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function formatDate(
|
|
525
|
+
date: Date,
|
|
526
|
+
options?: Intl.DateTimeFormatOptions & { timeZone?: string },
|
|
527
|
+
) {
|
|
528
|
+
const locale = getLocale();
|
|
529
|
+
const timeZone = options?.timeZone || getUserTimeZone();
|
|
530
|
+
const fmt = new Intl.DateTimeFormat(locale, {
|
|
531
|
+
year: "numeric",
|
|
532
|
+
month: "numeric",
|
|
533
|
+
day: "numeric",
|
|
534
|
+
hour: "numeric",
|
|
535
|
+
minute: "numeric",
|
|
536
|
+
second: "numeric",
|
|
537
|
+
hour12: false,
|
|
538
|
+
timeZone,
|
|
539
|
+
...options,
|
|
540
|
+
});
|
|
541
|
+
return fmt.format(date);
|
|
542
|
+
}
|
|
516
543
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
)
|
|
544
|
+
export function formatDateOnly(
|
|
545
|
+
date: Date,
|
|
546
|
+
options?: Intl.DateTimeFormatOptions & { timeZone?: string },
|
|
547
|
+
) {
|
|
548
|
+
const locale = getLocale();
|
|
549
|
+
const timeZone = options?.timeZone || getUserTimeZone();
|
|
550
|
+
const fmt = new Intl.DateTimeFormat(locale, {
|
|
551
|
+
year: "numeric",
|
|
552
|
+
month: "numeric",
|
|
553
|
+
day: "numeric",
|
|
554
|
+
timeZone,
|
|
555
|
+
...options,
|
|
556
|
+
});
|
|
557
|
+
return fmt.format(date);
|
|
558
|
+
}
|
|
521
559
|
|
|
522
|
-
export function
|
|
523
|
-
|
|
560
|
+
export function formatTime(
|
|
561
|
+
date: Date,
|
|
562
|
+
options?: Intl.DateTimeFormatOptions & { timeZone?: string },
|
|
563
|
+
) {
|
|
564
|
+
const locale = getLocale();
|
|
565
|
+
const timeZone = options?.timeZone || getUserTimeZone();
|
|
566
|
+
const fmt = new Intl.DateTimeFormat(locale, {
|
|
567
|
+
hour: "numeric",
|
|
568
|
+
minute: "numeric",
|
|
569
|
+
second: "numeric",
|
|
570
|
+
hour12: false,
|
|
571
|
+
timeZone,
|
|
572
|
+
...options,
|
|
573
|
+
});
|
|
574
|
+
return fmt.format(date);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
export function formatDateTime(
|
|
578
|
+
date: Date,
|
|
579
|
+
options?: Intl.DateTimeFormatOptions & { timeZone?: string },
|
|
580
|
+
) {
|
|
581
|
+
return formatDate(date, options);
|
|
524
582
|
}
|
|
525
583
|
|
|
526
584
|
export function findClosestFieldElement(node: Node | null): HTMLElement | null {
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-09-23
|
|
1
|
+
export const version = "1.0.4105";
|
|
2
|
+
export const buildDate = "2025-09-23 15:04:32";
|