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.
Files changed (41) hide show
  1. package/bin/agent-canvas.ts +3 -0
  2. package/bin/lib/commands/install.ts +7 -7
  3. package/bin/lib/commands/instructions.ts +66 -0
  4. package/bin/lib/instructions/component-callout.md +27 -0
  5. package/bin/lib/instructions/component-checklist.md +17 -0
  6. package/bin/lib/instructions/component-choice.md +27 -0
  7. package/bin/lib/instructions/component-codeblock.md +24 -0
  8. package/bin/lib/instructions/component-custom.md +34 -0
  9. package/bin/lib/instructions/component-diff.md +18 -0
  10. package/bin/lib/instructions/component-filepreview.md +15 -0
  11. package/bin/lib/instructions/component-image.md +17 -0
  12. package/bin/lib/instructions/component-item.md +43 -0
  13. package/bin/lib/instructions/component-markdown.md +33 -0
  14. package/bin/lib/instructions/component-mermaid.md +40 -0
  15. package/bin/lib/instructions/component-multichoice.md +19 -0
  16. package/bin/lib/instructions/component-note.md +11 -0
  17. package/bin/lib/instructions/component-priority.md +15 -0
  18. package/bin/lib/instructions/component-rangeinput.md +20 -0
  19. package/bin/lib/instructions/component-section.md +22 -0
  20. package/bin/lib/instructions/component-svg.md +31 -0
  21. package/bin/lib/instructions/component-table.md +21 -0
  22. package/bin/lib/instructions/component-usefeedback.md +33 -0
  23. package/bin/lib/instructions/component-userinput.md +17 -0
  24. package/bin/lib/instructions/flow-decision.md +53 -0
  25. package/bin/lib/instructions/flow-explain.md +47 -0
  26. package/bin/lib/instructions/flow-feature.md +188 -0
  27. package/bin/lib/instructions/flow-plan.md +106 -0
  28. package/bin/lib/instructions/flow-review.md +60 -0
  29. package/bin/lib/instructions/overview.md +173 -0
  30. package/bin/lib/instructions/theming.md +50 -0
  31. package/daemon/client/AnnotationSidebar.tsx +40 -20
  32. package/daemon/client/App.tsx +8 -1
  33. package/daemon/dist/client.js +35 -35
  34. package/daemon/src/compiler.ts +1 -0
  35. package/daemon/src/handlers/api.ts +3 -1
  36. package/daemon/src/server.ts +1 -1
  37. package/daemon/src/websocket.ts +62 -1
  38. package/package.json +1 -1
  39. package/skills/canvas/SKILL.md +9 -194
  40. package/skills/canvas/components.md +0 -403
  41. 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>
@@ -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 }}>