agent-canvas 0.1.16 → 0.1.18
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/bin/agent-canvas.ts +3 -0
- package/bin/lib/commands/install.ts +7 -7
- package/bin/lib/commands/instructions.ts +66 -0
- package/bin/lib/instructions/component-callout.md +27 -0
- package/bin/lib/instructions/component-checklist.md +17 -0
- package/bin/lib/instructions/component-choice.md +27 -0
- package/bin/lib/instructions/component-codeblock.md +24 -0
- package/bin/lib/instructions/component-custom.md +34 -0
- package/bin/lib/instructions/component-diff.md +18 -0
- package/bin/lib/instructions/component-filepreview.md +15 -0
- package/bin/lib/instructions/component-image.md +17 -0
- package/bin/lib/instructions/component-item.md +43 -0
- package/bin/lib/instructions/component-markdown.md +33 -0
- package/bin/lib/instructions/component-mermaid.md +40 -0
- package/bin/lib/instructions/component-multichoice.md +19 -0
- package/bin/lib/instructions/component-note.md +11 -0
- package/bin/lib/instructions/component-priority.md +15 -0
- package/bin/lib/instructions/component-rangeinput.md +20 -0
- package/bin/lib/instructions/component-section.md +22 -0
- package/bin/lib/instructions/component-svg.md +31 -0
- package/bin/lib/instructions/component-table.md +21 -0
- package/bin/lib/instructions/component-usefeedback.md +33 -0
- package/bin/lib/instructions/component-userinput.md +17 -0
- package/bin/lib/instructions/flow-decision.md +53 -0
- package/bin/lib/instructions/flow-explain.md +47 -0
- package/bin/lib/instructions/flow-feature.md +188 -0
- package/bin/lib/instructions/flow-plan.md +106 -0
- package/bin/lib/instructions/flow-review.md +60 -0
- package/bin/lib/instructions/overview.md +173 -0
- package/bin/lib/instructions/theming.md +50 -0
- package/daemon/client/AnnotationSidebar.tsx +40 -20
- package/daemon/client/App.tsx +8 -1
- package/daemon/dist/client.js +35 -35
- package/daemon/src/compiler.ts +1 -0
- package/daemon/src/handlers/api.ts +3 -1
- package/daemon/src/server.ts +1 -1
- package/daemon/src/websocket.ts +62 -1
- package/package.json +1 -1
- package/skills/canvas/SKILL.md +9 -194
- package/skills/canvas/components.md +0 -403
- package/skills/canvas/flows.md +0 -406
|
@@ -17,20 +17,21 @@ interface AnnotationSidebarProps {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function AnnotationSidebar({ onPreview, onSubmit, collapseButton }: AnnotationSidebarProps) {
|
|
20
|
-
const { isReadOnly, selectedRevision, currentRevision, revisions } = useContext(RevisionContext);
|
|
20
|
+
const { isReadOnly, selectedRevision, currentRevision, revisions, agentWatching } = useContext(RevisionContext);
|
|
21
21
|
const sessionId = useContext(SessionContext);
|
|
22
|
-
const isCurrentButSubmitted = isReadOnly && selectedRevision === currentRevision;
|
|
23
22
|
const selectedRevInfo = revisions.find((r) => r.revision === selectedRevision);
|
|
23
|
+
const isCurrentButSubmitted = isReadOnly && selectedRevision === currentRevision;
|
|
24
|
+
const feedbackConsumed = !!selectedRevInfo?.feedbackConsumed;
|
|
24
25
|
const roundLabel = selectedRevInfo?.label || `Round ${selectedRevision}`;
|
|
25
26
|
|
|
26
27
|
if (isReadOnly) {
|
|
27
|
-
return <ReadOnlyAnnotationSidebar sessionId={sessionId} revision={selectedRevision} label={roundLabel} waitingForUpdate={isCurrentButSubmitted} collapseButton={collapseButton} />;
|
|
28
|
+
return <ReadOnlyAnnotationSidebar sessionId={sessionId} revision={selectedRevision} label={roundLabel} waitingForUpdate={isCurrentButSubmitted} feedbackConsumed={feedbackConsumed} agentWatching={agentWatching} collapseButton={collapseButton} />;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
return <AnnotationSidebarInner onPreview={onPreview} onSubmit={onSubmit} collapseButton={collapseButton} />;
|
|
31
|
+
return <AnnotationSidebarInner onPreview={onPreview} onSubmit={onSubmit} agentWatching={agentWatching} collapseButton={collapseButton} />;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
function FeedbackDisplay({ sessionId, revision, label, waitingForUpdate, collapseButton }: { sessionId: string; revision: number; label: string; waitingForUpdate?: boolean; collapseButton?: React.ReactNode }) {
|
|
34
|
+
function FeedbackDisplay({ sessionId, revision, label, waitingForUpdate, feedbackConsumed, agentWatching, collapseButton }: { sessionId: string; revision: number; label: string; waitingForUpdate?: boolean; feedbackConsumed?: boolean; agentWatching?: boolean; collapseButton?: React.ReactNode }) {
|
|
34
35
|
const [feedback, setFeedback] = useState<string | null>(null);
|
|
35
36
|
const [loading, setLoading] = useState(true);
|
|
36
37
|
|
|
@@ -51,12 +52,7 @@ function FeedbackDisplay({ sessionId, revision, label, waitingForUpdate, collaps
|
|
|
51
52
|
{collapseButton}
|
|
52
53
|
</div>
|
|
53
54
|
|
|
54
|
-
{waitingForUpdate &&
|
|
55
|
-
<div className="mx-4 mb-3 px-3 py-2.5 rounded-lg bg-accent-green-muted flex items-center gap-2 flex-shrink-0">
|
|
56
|
-
<span className="w-2 h-2 rounded-full bg-accent-green animate-pulse" />
|
|
57
|
-
<span className="text-[12px] font-body text-accent-green">Waiting for next revision...</span>
|
|
58
|
-
</div>
|
|
59
|
-
)}
|
|
55
|
+
{waitingForUpdate && <WaitingBanner feedbackConsumed={feedbackConsumed} agentWatching={agentWatching} />}
|
|
60
56
|
|
|
61
57
|
<div className="flex-1 overflow-y-auto px-4">
|
|
62
58
|
{loading ? (
|
|
@@ -71,9 +67,34 @@ function FeedbackDisplay({ sessionId, revision, label, waitingForUpdate, collaps
|
|
|
71
67
|
);
|
|
72
68
|
}
|
|
73
69
|
|
|
70
|
+
function WaitingBanner({ feedbackConsumed, agentWatching }: { feedbackConsumed?: boolean; agentWatching?: boolean }) {
|
|
71
|
+
if (feedbackConsumed) {
|
|
72
|
+
return (
|
|
73
|
+
<div className="mx-4 mb-3 px-3 py-2.5 rounded-lg bg-accent-green-muted flex items-center gap-2 flex-shrink-0">
|
|
74
|
+
<span className="w-2 h-2 rounded-full bg-accent-green animate-pulse" />
|
|
75
|
+
<span className="text-[12px] font-body text-accent-green">Feedback received — waiting for next revision...</span>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (agentWatching) {
|
|
80
|
+
return (
|
|
81
|
+
<div className="mx-4 mb-3 px-3 py-2.5 rounded-lg bg-accent-blue-muted flex items-center gap-2 flex-shrink-0">
|
|
82
|
+
<span className="w-2 h-2 rounded-full bg-accent-blue animate-pulse" />
|
|
83
|
+
<span className="text-[12px] font-body text-accent-blue">Waiting for agent to pick up feedback...</span>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
return (
|
|
88
|
+
<div className="mx-4 mb-3 px-3 py-2.5 rounded-lg bg-accent-amber-muted flex items-center gap-2 flex-shrink-0">
|
|
89
|
+
<span className="w-2 h-2 rounded-full bg-accent-amber" />
|
|
90
|
+
<span className="text-[12px] font-body text-accent-amber">Agent disconnected — tell Claude to check feedback</span>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
74
95
|
type ReadOnlyTab = "feedback" | "annotations";
|
|
75
96
|
|
|
76
|
-
function ReadOnlyAnnotationSidebar({ sessionId, revision, label, waitingForUpdate, collapseButton }: { sessionId: string; revision: number; label: string; waitingForUpdate?: boolean; collapseButton?: React.ReactNode }) {
|
|
97
|
+
function ReadOnlyAnnotationSidebar({ sessionId, revision, label, waitingForUpdate, feedbackConsumed, agentWatching, collapseButton }: { sessionId: string; revision: number; label: string; waitingForUpdate?: boolean; feedbackConsumed?: boolean; agentWatching?: boolean; collapseButton?: React.ReactNode }) {
|
|
77
98
|
const { annotations, generalNote, activeAnnotationId, setActiveAnnotationId } = useAnnotations();
|
|
78
99
|
const { setActiveView } = useContext(ActiveViewContext);
|
|
79
100
|
const hasAnnotations = annotations.length > 0 || generalNote.trim().length > 0;
|
|
@@ -81,7 +102,7 @@ function ReadOnlyAnnotationSidebar({ sessionId, revision, label, waitingForUpdat
|
|
|
81
102
|
|
|
82
103
|
// If no annotations in localStorage, just show feedback
|
|
83
104
|
if (!hasAnnotations) {
|
|
84
|
-
return <FeedbackDisplay sessionId={sessionId} revision={revision} label={label} waitingForUpdate={waitingForUpdate} collapseButton={collapseButton} />;
|
|
105
|
+
return <FeedbackDisplay sessionId={sessionId} revision={revision} label={label} waitingForUpdate={waitingForUpdate} feedbackConsumed={feedbackConsumed} agentWatching={agentWatching} collapseButton={collapseButton} />;
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
return (
|
|
@@ -114,12 +135,7 @@ function ReadOnlyAnnotationSidebar({ sessionId, revision, label, waitingForUpdat
|
|
|
114
135
|
{collapseButton}
|
|
115
136
|
</div>
|
|
116
137
|
|
|
117
|
-
{waitingForUpdate &&
|
|
118
|
-
<div className="mx-4 mb-3 px-3 py-2.5 rounded-lg bg-accent-green-muted flex items-center gap-2 flex-shrink-0">
|
|
119
|
-
<span className="w-2 h-2 rounded-full bg-accent-green animate-pulse" />
|
|
120
|
-
<span className="text-[12px] font-body text-accent-green">Waiting for next revision...</span>
|
|
121
|
-
</div>
|
|
122
|
-
)}
|
|
138
|
+
{waitingForUpdate && <WaitingBanner feedbackConsumed={feedbackConsumed} agentWatching={agentWatching} />}
|
|
123
139
|
|
|
124
140
|
{activeTab === "feedback" ? (
|
|
125
141
|
<FeedbackDisplayContent sessionId={sessionId} revision={revision} />
|
|
@@ -287,7 +303,7 @@ function ReadOnlyAnnotationList({ annotations, generalNote, activeAnnotationId,
|
|
|
287
303
|
);
|
|
288
304
|
}
|
|
289
305
|
|
|
290
|
-
function AnnotationSidebarInner({ onPreview, onSubmit, collapseButton }: AnnotationSidebarProps) {
|
|
306
|
+
function AnnotationSidebarInner({ onPreview, onSubmit, agentWatching, collapseButton }: AnnotationSidebarProps & { agentWatching: boolean }) {
|
|
291
307
|
const {
|
|
292
308
|
annotations, updateAnnotation, removeAnnotation,
|
|
293
309
|
addAnnotationImage, removeAnnotationImage,
|
|
@@ -422,6 +438,10 @@ function AnnotationSidebarInner({ onPreview, onSubmit, collapseButton }: Annotat
|
|
|
422
438
|
{annotations.length > 0 && (
|
|
423
439
|
<span className="inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-border-subtle text-[10px] font-medium text-text-secondary">{annotations.length}</span>
|
|
424
440
|
)}
|
|
441
|
+
<span
|
|
442
|
+
className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${agentWatching ? "bg-accent-green" : "bg-accent-amber"}`}
|
|
443
|
+
title={agentWatching ? "Agent connected" : "Agent disconnected"}
|
|
444
|
+
/>
|
|
425
445
|
</span>
|
|
426
446
|
{collapseButton}
|
|
427
447
|
</div>
|
package/daemon/client/App.tsx
CHANGED
|
@@ -32,6 +32,7 @@ export interface RevisionInfo {
|
|
|
32
32
|
canvasFiles: CanvasFileInfo[];
|
|
33
33
|
createdAt: string;
|
|
34
34
|
hasFeedback: boolean;
|
|
35
|
+
feedbackConsumed: boolean;
|
|
35
36
|
response?: string;
|
|
36
37
|
}
|
|
37
38
|
|
|
@@ -57,6 +58,7 @@ export const RevisionContext = createContext<{
|
|
|
57
58
|
isReadOnly: boolean;
|
|
58
59
|
compareRevision: { left: number; right: number } | null;
|
|
59
60
|
setCompareRevision: (rev: { left: number; right: number } | null) => void;
|
|
61
|
+
agentWatching: boolean;
|
|
60
62
|
}>({
|
|
61
63
|
currentRevision: 1,
|
|
62
64
|
selectedRevision: 1,
|
|
@@ -65,6 +67,7 @@ export const RevisionContext = createContext<{
|
|
|
65
67
|
isReadOnly: false,
|
|
66
68
|
compareRevision: null,
|
|
67
69
|
setCompareRevision: () => {},
|
|
70
|
+
agentWatching: false,
|
|
68
71
|
});
|
|
69
72
|
|
|
70
73
|
function resolveTheme(pref: string): "light" | "dark" {
|
|
@@ -179,6 +182,7 @@ function App() {
|
|
|
179
182
|
const [revisions, setRevisions] = useState<RevisionInfo[]>([]);
|
|
180
183
|
const [compareRevision, setCompareRevision] = useState<{ left: number; right: number } | null>(null);
|
|
181
184
|
const [connected, setConnected] = useState(false);
|
|
185
|
+
const [agentWatching, setAgentWatching] = useState(false);
|
|
182
186
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
183
187
|
const [canvasFiles, setCanvasFiles] = useState<string[]>([]);
|
|
184
188
|
const [activeView, setActiveViewRaw] = useState<ActiveView>({ type: "overview" });
|
|
@@ -314,6 +318,9 @@ function App() {
|
|
|
314
318
|
if (data.type === "revision-updated") {
|
|
315
319
|
if (data.revisions) setRevisions(data.revisions);
|
|
316
320
|
}
|
|
321
|
+
if (data.type === "watcher-status") {
|
|
322
|
+
setAgentWatching(!!data.watching);
|
|
323
|
+
}
|
|
317
324
|
} catch {}
|
|
318
325
|
};
|
|
319
326
|
};
|
|
@@ -336,7 +343,7 @@ function App() {
|
|
|
336
343
|
|
|
337
344
|
return (
|
|
338
345
|
<SessionContext.Provider value={sessionId}>
|
|
339
|
-
<RevisionContext.Provider value={{ currentRevision, selectedRevision, revisions, setSelectedRevision, isReadOnly, compareRevision, setCompareRevision }}>
|
|
346
|
+
<RevisionContext.Provider value={{ currentRevision, selectedRevision, revisions, setSelectedRevision, isReadOnly, compareRevision, setCompareRevision, agentWatching }}>
|
|
340
347
|
<AnnotationProvider key={`${sessionId}:${selectedRevision}`} sessionId={sessionId} revision={selectedRevision} isReadOnly={isReadOnly}>
|
|
341
348
|
<ActiveViewContext.Provider value={{ activeView, setActiveView, openFiles, closeFile, canvasFiles }}>
|
|
342
349
|
<ActiveViewCtx.Provider value={{ setActiveView }}>
|