konpeki 0.2.0 → 0.3.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.
Files changed (39) hide show
  1. package/AGENTS.md +1 -1
  2. package/CONTRIBUTING.md +36 -0
  3. package/README.md +54 -18
  4. package/SECURITY.md +22 -0
  5. package/SETUP.md +112 -51
  6. package/composition/README.md +16 -3
  7. package/composition/compile.ts +1 -1
  8. package/composition/schema.json +9 -0
  9. package/composition/schema.ts +3 -1
  10. package/composition/types.ts +3 -1
  11. package/design/themes/README.md +25 -7
  12. package/design/themes/index.ts +15 -4
  13. package/docs/development.md +71 -11
  14. package/docs/workflow.md +11 -4
  15. package/index.html +17 -1
  16. package/package.json +8 -2
  17. package/plugin.json +22 -0
  18. package/public/og.png +0 -0
  19. package/runtime/konpeki.mjs +41 -13
  20. package/skills/konpeki/SKILL.md +186 -0
  21. package/skills/konpeki/assets/blank.json +23 -0
  22. package/skills/konpeki/scripts/ensure-runtime.mjs +69 -0
  23. package/skills/konpeki/scripts/prepare-document.mjs +40 -0
  24. package/slides/introducing-konpeki/PROMPT.md +21 -0
  25. package/slides/introducing-konpeki/README.md +52 -30
  26. package/slides/introducing-konpeki/SOURCE.md +16 -10
  27. package/slides/introducing-konpeki/author.ts +44 -42
  28. package/slides/introducing-konpeki/composition.json +135 -135
  29. package/src/app/App.tsx +87 -19
  30. package/src/components/Canvas.tsx +1 -1
  31. package/src/components/InspectorPanel.tsx +93 -40
  32. package/src/components/WorkspaceChrome.tsx +92 -5
  33. package/src/lib/storage.ts +38 -10
  34. package/src/main.tsx +3 -0
  35. package/src/styles/chrome.css +97 -25
  36. package/src/styles/feedback.css +20 -3
  37. package/src/styles/right-panel.css +28 -27
  38. package/src/styles/shell.css +60 -29
  39. package/.agents/skills/authoring-visuals/SKILL.md +0 -93
@@ -1,5 +1,3 @@
1
- .document-island,
2
- .action-island,
3
1
  .component-dock {
4
2
  position: fixed;
5
3
  z-index: 40;
@@ -11,18 +9,25 @@
11
9
  }
12
10
 
13
11
  .document-island {
14
- top: 20px;
15
- left: 20px;
16
- width: 252px;
17
- height: 60px;
12
+ position: relative;
13
+ z-index: 2;
14
+ display: flex;
15
+ align-items: center;
16
+ flex: none;
17
+ width: 100%;
18
+ height: var(--panel-header-height);
18
19
  gap: 10px;
19
20
  padding: 8px 10px;
20
- border-radius: 14px;
21
+ border-bottom: 1px solid var(--ui-border);
22
+ }
23
+
24
+ .left-collapsed .document-island {
25
+ border-bottom-color: transparent;
21
26
  }
22
27
 
23
- .workspace:has(.left-panel:not(.collapsed)) .document-island {
24
- border-radius: 12px 12px 0 0;
25
- box-shadow: none;
28
+ .left-collapsed .document-title,
29
+ .left-collapsed .document-title-error {
30
+ visibility: hidden;
26
31
  }
27
32
 
28
33
  .document-island img {
@@ -32,10 +37,6 @@
32
37
  object-fit: contain;
33
38
  }
34
39
 
35
- .document-island .panel-collapse-icon {
36
- transform: rotate(-90deg);
37
- }
38
-
39
40
  .document-title {
40
41
  min-width: 0;
41
42
  flex: 1;
@@ -105,20 +106,15 @@
105
106
  }
106
107
 
107
108
  .action-island {
108
- bottom: 92px;
109
- left: 20px;
110
- width: 252px;
111
- min-width: 252px;
112
- height: 56px;
109
+ position: relative;
110
+ display: flex;
111
+ align-items: center;
112
+ flex: none;
113
+ width: calc(var(--panel-width) - 2px);
114
+ height: 54px;
113
115
  gap: 4px;
114
116
  padding: 7px;
115
117
  border-top: 1px solid var(--ui-border);
116
- border-radius: 0 0 12px 12px;
117
- box-shadow: none;
118
- }
119
-
120
- .left-collapsed .action-island {
121
- visibility: hidden;
122
118
  }
123
119
 
124
120
  .action-island button {
@@ -146,6 +142,82 @@
146
142
  justify-content: center;
147
143
  }
148
144
 
145
+ .browser-menu {
146
+ position: relative;
147
+ min-width: 0;
148
+ }
149
+
150
+ .browser-menu > summary {
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ height: 40px;
155
+ padding: 0 12px;
156
+ border-radius: 7px;
157
+ cursor: pointer;
158
+ font-size: 13px;
159
+ font-weight: 500;
160
+ list-style: none;
161
+ }
162
+
163
+ .browser-menu > summary::-webkit-details-marker {
164
+ display: none;
165
+ }
166
+
167
+ .browser-menu > summary:hover,
168
+ .browser-menu[open] > summary {
169
+ background: var(--ui-hover);
170
+ }
171
+
172
+ .browser-menu-popover {
173
+ position: absolute;
174
+ bottom: calc(100% + 14px);
175
+ left: -95px;
176
+ display: grid;
177
+ width: 304px;
178
+ gap: 12px;
179
+ padding: 16px;
180
+ border: 1px solid var(--ui-border);
181
+ border-radius: 12px;
182
+ background: var(--ui-surface);
183
+ box-shadow: var(--ui-shadow);
184
+ }
185
+
186
+ .browser-menu-popover strong {
187
+ font-size: 13px;
188
+ font-weight: 600;
189
+ }
190
+
191
+ .browser-menu-popover p {
192
+ color: var(--ui-muted);
193
+ font-size: 12px;
194
+ line-height: 1.5;
195
+ }
196
+
197
+ .browser-menu-actions {
198
+ display: grid;
199
+ grid-template-columns: 1fr 1fr;
200
+ gap: 6px;
201
+ }
202
+
203
+ .action-island .browser-menu-actions button {
204
+ justify-content: flex-start;
205
+ min-width: 0;
206
+ border-color: var(--ui-border);
207
+ background: var(--ui-surface);
208
+ font-size: 12px;
209
+ }
210
+
211
+ .browser-agent-handoff {
212
+ padding-top: 10px;
213
+ border-top: 1px solid var(--ui-border);
214
+ }
215
+
216
+ .browser-agent-handoff a {
217
+ color: var(--accent);
218
+ font-weight: 500;
219
+ }
220
+
149
221
  .action-island button.primary {
150
222
  background: white;
151
223
  color: var(--ui-text);
@@ -71,14 +71,31 @@
71
71
  }
72
72
  }
73
73
  .recovery {
74
+ position: fixed;
75
+ bottom: 100px;
76
+ left: 50%;
77
+ transform: translateX(-50%);
78
+ z-index: 50;
74
79
  display: flex;
75
80
  justify-content: center;
76
81
  align-items: center;
77
- gap: 20px;
78
- background: #fff;
79
- border-bottom: 1px solid #ccc;
82
+ gap: 12px;
83
+ width: max-content;
84
+ max-width: min(520px, max(240px, calc(100vw - 744px)), calc(100vw - 40px));
85
+ background: var(--ui-surface);
86
+ border: 1px solid var(--ui-border);
87
+ border-radius: 12px;
88
+ box-shadow: var(--ui-shadow);
80
89
  padding: 12px;
81
90
  font-size: 13px;
91
+ line-height: 1.5;
92
+ }
93
+ .recovery > span {
94
+ min-width: 0;
95
+ overflow-wrap: anywhere;
96
+ }
97
+ .recovery > button {
98
+ flex: none;
82
99
  }
83
100
  @media (prefers-reduced-motion: reduce) {
84
101
  *,
@@ -10,6 +10,10 @@
10
10
  margin-bottom: 16px;
11
11
  }
12
12
 
13
+ .inspector-content:has(> .page-number-picker) legend {
14
+ margin-bottom: 7px;
15
+ }
16
+
13
17
  .field-error {
14
18
  color: #a02020 !important;
15
19
  }
@@ -202,14 +206,6 @@
202
206
  white-space: nowrap;
203
207
  }
204
208
 
205
- .theme-options button[data-theme="precision"] > span:first-child {
206
- font-family: "Noto Sans", sans-serif;
207
- }
208
-
209
- .theme-options button[data-theme="editorial"] > span:first-child {
210
- font-family: Georgia, serif;
211
- }
212
-
213
209
  .theme-swatches {
214
210
  display: flex;
215
211
  gap: 3px;
@@ -356,6 +352,11 @@
356
352
  color: #565656;
357
353
  }
358
354
 
355
+ .field:has(> select[name="Font"]) > span {
356
+ color: var(--ui-text);
357
+ font-weight: 500;
358
+ }
359
+
359
360
  .field textarea {
360
361
  resize: none;
361
362
  overflow-y: auto;
@@ -799,6 +800,13 @@
799
800
  display: block;
800
801
  }
801
802
 
803
+ .appearance-preview[data-property="template"] svg {
804
+ position: absolute;
805
+ inset: 0;
806
+ width: 100%;
807
+ height: 100%;
808
+ }
809
+
802
810
  .appearance-preview[data-property="template"] i {
803
811
  position: absolute;
804
812
  z-index: 1;
@@ -880,24 +888,6 @@
880
888
  .appearance-preview[data-property="template"][data-value="treemap"] i:nth-child(3) { right: 8px; bottom: 3px; width: 5px; height: 7px; }
881
889
  .appearance-preview[data-property="template"][data-value="treemap"] i:nth-child(4) { right: 3px; bottom: 3px; width: 3px; height: 7px; background: var(--preview-secondary); }
882
890
 
883
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(1) { left: 5px; bottom: 5px; }
884
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(2) { left: 13px; bottom: 9px; }
885
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(3) { left: 22px; bottom: 12px; }
886
- .appearance-preview[data-property="template"][data-value="scatter"] i:nth-child(4) { right: 5px; top: 4px; width: 7px; height: 7px; background: var(--preview-accent); }
887
-
888
- .appearance-preview[data-property="template"][data-value="sankey"]::before,
889
- .appearance-preview[data-property="template"][data-value="sankey"]::after {
890
- position: absolute;
891
- left: 4px;
892
- width: 29px;
893
- border-top: 5px solid var(--preview-accent);
894
- border-radius: 50%;
895
- content: "";
896
- }
897
- .appearance-preview[data-property="template"][data-value="sankey"]::before { top: 7px; transform: rotate(8deg); }
898
- .appearance-preview[data-property="template"][data-value="sankey"]::after { bottom: 6px; border-color: var(--preview-muted); transform: rotate(-9deg); }
899
- .appearance-preview[data-property="template"][data-value="sankey"] i { display: none; }
900
-
901
891
  .appearance-preview[data-property="template"][data-value="linear"]::before,
902
892
  .appearance-preview[data-property="template"][data-value="request-flow"]::before {
903
893
  position: absolute;
@@ -1114,10 +1104,14 @@ legend {
1114
1104
  place-items: center;
1115
1105
  }
1116
1106
 
1117
- .diagram-type-category button:hover {
1107
+ .diagram-type-category button:hover:not(:disabled) {
1118
1108
  background: var(--ui-hover);
1119
1109
  }
1120
1110
 
1111
+ .diagram-type-category button:disabled {
1112
+ opacity: 0.48;
1113
+ }
1114
+
1121
1115
  .diagram-type-category button.selected {
1122
1116
  border-color: color-mix(in srgb, var(--accent) 45%, white);
1123
1117
  background: var(--ui-selected);
@@ -1152,6 +1146,13 @@ legend {
1152
1146
  stroke: none;
1153
1147
  }
1154
1148
 
1149
+ .chart-type-options .appearance-preview {
1150
+ margin: 4px 0;
1151
+ border: 0;
1152
+ background: transparent;
1153
+ transform: scale(1.333333);
1154
+ }
1155
+
1155
1156
  .visualization-description {
1156
1157
  display: block;
1157
1158
  margin-top: 8px;
@@ -11,67 +11,85 @@
11
11
  top: 8px;
12
12
  }
13
13
  .workspace {
14
+ --panel-duration: 200ms;
15
+ --panel-easing: cubic-bezier(0.2, 0, 0, 1);
16
+ --panel-header-height: 58px;
14
17
  position: relative;
15
18
  height: 100dvh;
16
19
  min-height: 100dvh;
17
20
  overflow: hidden;
18
21
  background: var(--ui-bg);
19
22
  }
20
- .left-panel,
23
+ .left-sidebar,
21
24
  .right-panel {
22
25
  position: fixed;
23
- top: 92px;
24
- bottom: 92px;
26
+ top: 20px;
27
+ height: calc(100dvh - 112px);
28
+ width: var(--panel-width);
25
29
  z-index: 30;
30
+ display: flex;
31
+ flex-direction: column;
32
+ overflow: hidden;
26
33
  background: var(--ui-surface);
27
34
  min-height: 0;
28
35
  border: 1px solid var(--ui-border);
29
36
  border-radius: 12px;
30
37
  box-shadow: var(--ui-shadow);
38
+ transition: width var(--panel-duration) var(--panel-easing),
39
+ height var(--panel-duration) var(--panel-easing);
31
40
  }
32
- .left-panel {
33
- top: 80px;
34
- bottom: 148px;
41
+ .left-sidebar {
42
+ --panel-width: 252px;
35
43
  left: 20px;
36
- width: 252px;
37
- border-top: 0;
38
- border-bottom: 0;
39
- border-radius: 0;
40
- display: flex;
41
- flex-direction: column;
42
- overflow: hidden;
44
+ z-index: 40;
45
+ }
46
+ .left-sidebar.collapsed {
47
+ width: 107px;
48
+ height: calc(var(--panel-header-height) + 2px);
49
+ }
50
+ .left-sidebar:not(.collapsed):has(.browser-menu[open]) {
51
+ overflow: visible;
43
52
  }
44
53
  .right-panel {
45
- top: 20px;
54
+ --panel-width: min(328px, calc(100vw - 40px));
46
55
  right: 20px;
47
- display: flex;
48
- flex-direction: column;
49
- width: min(328px, calc(100vw - 40px));
50
- overflow: hidden;
51
56
  }
52
57
  .right-panel.collapsed {
53
- bottom: auto;
54
58
  width: 50px;
55
- height: 56px;
59
+ height: calc(var(--panel-header-height) + 2px);
56
60
  }
57
61
  .right-panel.collapsed > .panel-toolbar {
58
- height: 54px;
59
- justify-content: flex-end;
60
- padding: 0 8px;
61
- border-bottom: 0;
62
+ gap: 0;
63
+ padding: 0 4px;
64
+ border-bottom-color: transparent;
62
65
  }
63
- .right-panel.collapsed .panel-tabs,
64
- .right-panel.collapsed .right-panel-body {
65
- display: none;
66
+ .right-panel.collapsed .panel-tabs {
67
+ visibility: hidden;
66
68
  }
69
+ .left-panel,
67
70
  .right-panel-body {
71
+ width: calc(var(--panel-width) - 2px);
68
72
  display: flex;
69
73
  flex-direction: column;
70
74
  flex: 1;
71
75
  min-height: 0;
76
+ overflow: hidden;
77
+ }
78
+ .right-panel-body {
79
+ align-self: flex-end;
72
80
  }
73
- .left-panel.collapsed {
81
+ .left-panel,
82
+ .action-island,
83
+ .right-panel-body {
84
+ transition: opacity var(--panel-duration) var(--panel-easing),
85
+ visibility 0s;
86
+ }
87
+ .left-panel.collapsed,
88
+ .left-collapsed .action-island,
89
+ .right-panel.collapsed .right-panel-body {
90
+ opacity: 0;
74
91
  visibility: hidden;
92
+ transition-delay: 0s, var(--panel-duration);
75
93
  }
76
94
  .panel-toolbar {
77
95
  position: sticky;
@@ -91,8 +109,13 @@
91
109
  }
92
110
  .right-panel > .panel-toolbar {
93
111
  flex: none;
94
- height: 55px;
112
+ display: grid;
113
+ grid-template-columns: minmax(0, 1fr) 40px;
114
+ height: var(--panel-header-height);
95
115
  padding: 0 8px 0 12px;
116
+ overflow: hidden;
117
+ transition: padding var(--panel-duration) var(--panel-easing),
118
+ gap var(--panel-duration) var(--panel-easing);
96
119
  }
97
120
  .panel-heading {
98
121
  flex: 1;
@@ -197,6 +220,8 @@
197
220
  align-items: center;
198
221
  justify-content: center;
199
222
  min-width: 0;
223
+ transition: padding-left var(--panel-duration) var(--panel-easing),
224
+ padding-right var(--panel-duration) var(--panel-easing);
200
225
  }
201
226
  .workspace.left-collapsed .stage {
202
227
  padding-left: 96px;
@@ -299,3 +324,9 @@
299
324
  padding: 96px 16px 110px;
300
325
  }
301
326
  }
327
+
328
+ @media (prefers-reduced-motion: reduce) {
329
+ .workspace {
330
+ --panel-duration: 0ms;
331
+ }
332
+ }
@@ -1,93 +0,0 @@
1
- ---
2
- name: authoring-visuals
3
- description: Creates and revises editable Konpeki visuals from source material. Use for social graphics, article headers, visual explanations and presentations, including revisions to an existing composition.
4
- ---
5
-
6
- # Authoring visuals with Konpeki
7
-
8
- Deliver an editable composition and visually reviewed output. This skill needs
9
- the surrounding Konpeki runtime and resources; if they are unavailable, follow
10
- [SETUP.md](../../../SETUP.md) first. Paths here are relative to this file;
11
- run commands below from the user's workspace with Konpeki installed locally.
12
- For repository development, substitute `pnpm konpeki` for
13
- `npm exec --no -- konpeki`. Keep authored documents outside `node_modules`.
14
-
15
- ## 1. Interpret the brief
16
-
17
- Read [project rules](../../../AGENTS.md) and
18
- [authoring policy](../../../AUTHORING.md). Use the user's existing prompt as the
19
- brief; do not ask them to repeat it in the canvas. Establish the source facts,
20
- audience, takeaway and destination. Ask only when missing facts or conflicting
21
- requirements prevent a faithful result.
22
-
23
- Use `default` authoring mode unless requested otherwise. Explicit visual
24
- preferences override taste defaults, not factual fidelity or readability. Use
25
- the policy's [comparison workflow](../../../AUTHORING.md#explore-an-uncertain-direction)
26
- only when requested or accepted. A single page is a complete creation; choose
27
- dimensions for its destination rather than assuming a slide deck.
28
-
29
- ## 2. Author or revise the composition
30
-
31
- Read the [composition contract](../../../composition/README.md). For a new visual,
32
- create `slides/<name>/composition.json` unless the user supplies another path.
33
- Save the creative brief in `PROMPT.md` and substantial facts, citations and asset
34
- provenance in `SOURCE.md`. Separate assumptions from supplied facts. Preserve
35
- creative requests accurately, but omit private coordination and environment or
36
- agent metadata; label excerpts and redactions rather than calling them verbatim.
37
-
38
- For revisions, reread the current file first. Preserve unrelated content,
39
- component/vector IDs and human-edited geometry. Honor explicit chart or diagram
40
- choices. Recompose for a new aspect ratio instead of stretching or cropping.
41
-
42
- Prefer native text and semantic components. When standard drafts cannot express
43
- the visual, use editable vectors inside their owning component. Reuse
44
- [design resources](../../../design/README.md) and reference examples as needed.
45
- Trusted React may generate SVG for conversion, but imported JSX must not execute
46
- in the canvas or become a second document source.
47
-
48
- ## 3. Validate, render and repair
49
-
50
- ```sh
51
- npm exec --no -- konpeki validate slides/<name>/composition.json
52
- npm exec --no -- konpeki preview slides/<name>/composition.json
53
- ```
54
-
55
- Reuse an active file-backed preview for the same document when available. Open
56
- the exact session URL, or its host-approved remote preview equivalent. Inspect
57
- every affected page and requested theme at presentation and smaller review sizes
58
- after fonts load. Check factual fidelity, text bounds, contrast, reading order
59
- and relationships. Repair consequential issues and inspect fresh renders.
60
-
61
- Follow [verification guidance](../../../docs/development.md#verification) for
62
- code changes. Validation alone is not visual review. If a required check cannot
63
- run, state the limitation; do not claim it passed. Honor requested checkpoints;
64
- otherwise continue to finished output.
65
-
66
- ## 4. Deliver and continue revisions
67
-
68
- Return the composition path, usable preview, reviewed images or requested
69
- exports, source attribution and verification limitations. Verify exports
70
- separately; browser images do not prove editable PDF/PPTX or font fidelity.
71
- Include any generator source while keeping composition JSON authoritative.
72
-
73
- Keep revision requests in agent chat by default. When explicitly waiting for a
74
- canvas request, run `npm exec --no -- konpeki wait <composition.json>` alongside the preview.
75
- **Build it** submits a request; it does not launch an agent. On receiving it,
76
- reread the named file and compare its revision with the request. If it changed,
77
- reconcile against the latest document instead of applying a stale rewrite.
78
- Apply every attached note to its named page, component or vector-element ID;
79
- without notes, respect the selected scope. Preserve unrelated edits and stable
80
- IDs. A request is already marked working when `wait` returns; it is not deleted.
81
- Validate, render, inspect and repair the result, then run
82
- `npm exec --no -- konpeki finish <composition.json> <request-id> --message "Updated and checked"`.
83
- File changes alone do not resolve notes. If blocked, finish with
84
- `--status needs-clarification --message "..."` or `--status failed --message "..."`;
85
- unresolved notes remain for retry. Never mark a partially handled batch done.
86
- Use `konpeki request <composition.json>` to recover an interrupted request and
87
- verify it is still active before further writes. Cancellation does not stop your
88
- process: stop work if the request is no longer active. Do not edit the feedback
89
- sidecar directly. Return to `wait` only when the person requested a continuing loop.
90
-
91
- See [canvas workflow](../../../docs/workflow.md) for the full handoff contract.
92
- Never bypass revision checks or mutate hidden browser storage to replace the
93
- document. Do not publish without permission.