devglide 0.1.1

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 (252) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +338 -0
  3. package/bin/claude-md-template.js +94 -0
  4. package/bin/devglide.js +387 -0
  5. package/package.json +85 -0
  6. package/pnpm-workspace.yaml +3 -0
  7. package/src/apps/coder/.turbo/turbo-lint.log +5 -0
  8. package/src/apps/coder/package.json +16 -0
  9. package/src/apps/coder/public/favicon.svg +7 -0
  10. package/src/apps/coder/public/page.css +275 -0
  11. package/src/apps/coder/public/page.js +528 -0
  12. package/src/apps/coder/server.js +3 -0
  13. package/src/apps/documentation/public/page.css +597 -0
  14. package/src/apps/documentation/public/page.js +609 -0
  15. package/src/apps/kanban/.turbo/turbo-lint.log +97 -0
  16. package/src/apps/kanban/.turbo/turbo-typecheck.log +5 -0
  17. package/src/apps/kanban/package.json +32 -0
  18. package/src/apps/kanban/public/favicon.svg +7 -0
  19. package/src/apps/kanban/public/page.css +1010 -0
  20. package/src/apps/kanban/public/page.js +1730 -0
  21. package/src/apps/kanban/public/vendor/marked.min.js +6 -0
  22. package/src/apps/kanban/public/vendor/sortable.min.js +2 -0
  23. package/src/apps/kanban/src/db.ts +319 -0
  24. package/src/apps/kanban/src/index.ts +14 -0
  25. package/src/apps/kanban/src/mcp-helpers.test.ts +88 -0
  26. package/src/apps/kanban/src/mcp-helpers.ts +60 -0
  27. package/src/apps/kanban/src/mcp.ts +59 -0
  28. package/src/apps/kanban/src/routes/attachments.ts +161 -0
  29. package/src/apps/kanban/src/routes/features.ts +233 -0
  30. package/src/apps/kanban/src/routes/issues.ts +373 -0
  31. package/src/apps/kanban/src/tools/feature-tools.ts +164 -0
  32. package/src/apps/kanban/src/tools/item-tools.ts +307 -0
  33. package/src/apps/kanban/src/tools/versioned-entry-tools.ts +72 -0
  34. package/src/apps/kanban/tsconfig.check.json +9 -0
  35. package/src/apps/kanban/tsconfig.json +9 -0
  36. package/src/apps/keymap/.turbo/turbo-lint.log +5 -0
  37. package/src/apps/keymap/package.json +16 -0
  38. package/src/apps/keymap/public/page.css +275 -0
  39. package/src/apps/keymap/public/page.js +294 -0
  40. package/src/apps/keymap/server.js +25 -0
  41. package/src/apps/log/.turbo/turbo-build.log +5 -0
  42. package/src/apps/log/.turbo/turbo-lint.log +45 -0
  43. package/src/apps/log/.turbo/turbo-typecheck.log +5 -0
  44. package/src/apps/log/node_modules/.bin/tsc +21 -0
  45. package/src/apps/log/node_modules/.bin/tsserver +21 -0
  46. package/src/apps/log/node_modules/.bin/tsx +21 -0
  47. package/src/apps/log/package.json +36 -0
  48. package/src/apps/log/public/console-sniffer.js +221 -0
  49. package/src/apps/log/public/favicon.svg +7 -0
  50. package/src/apps/log/public/page.css +322 -0
  51. package/src/apps/log/public/page.js +463 -0
  52. package/src/apps/log/src/index.ts +9 -0
  53. package/src/apps/log/src/mcp.ts +122 -0
  54. package/src/apps/log/src/routes/log.ts +333 -0
  55. package/src/apps/log/src/routes/status.ts +25 -0
  56. package/src/apps/log/src/server-sniffer.ts +118 -0
  57. package/src/apps/log/src/services/file-patterns.ts +39 -0
  58. package/src/apps/log/src/services/file-tailer.ts +228 -0
  59. package/src/apps/log/src/services/line-parser.ts +94 -0
  60. package/src/apps/log/src/services/log-writer.ts +39 -0
  61. package/src/apps/log/tsconfig.json +8 -0
  62. package/src/apps/prompts/.turbo/turbo-build.log +5 -0
  63. package/src/apps/prompts/.turbo/turbo-lint.log +24 -0
  64. package/src/apps/prompts/.turbo/turbo-typecheck.log +5 -0
  65. package/src/apps/prompts/mcp.ts +175 -0
  66. package/src/apps/prompts/node_modules/.bin/tsc +21 -0
  67. package/src/apps/prompts/node_modules/.bin/tsserver +21 -0
  68. package/src/apps/prompts/node_modules/.bin/tsx +21 -0
  69. package/src/apps/prompts/package.json +25 -0
  70. package/src/apps/prompts/public/page.css +315 -0
  71. package/src/apps/prompts/public/page.js +541 -0
  72. package/src/apps/prompts/services/prompt-store.ts +212 -0
  73. package/src/apps/prompts/src/index.ts +9 -0
  74. package/src/apps/prompts/tsconfig.json +8 -0
  75. package/src/apps/prompts/types.ts +27 -0
  76. package/src/apps/shell/.turbo/turbo-build.log +5 -0
  77. package/src/apps/shell/.turbo/turbo-lint.log +34 -0
  78. package/src/apps/shell/.turbo/turbo-typecheck.log +5 -0
  79. package/src/apps/shell/package.json +35 -0
  80. package/src/apps/shell/public/favicon.svg +7 -0
  81. package/src/apps/shell/public/page.css +407 -0
  82. package/src/apps/shell/public/page.js +1577 -0
  83. package/src/apps/shell/src/index.ts +150 -0
  84. package/src/apps/shell/src/mcp.ts +398 -0
  85. package/src/apps/shell/src/shell-types.ts +41 -0
  86. package/src/apps/shell/tsconfig.json +8 -0
  87. package/src/apps/test/.turbo/turbo-build.log +5 -0
  88. package/src/apps/test/.turbo/turbo-lint.log +27 -0
  89. package/src/apps/test/.turbo/turbo-typecheck.log +5 -0
  90. package/src/apps/test/node_modules/.bin/tsc +21 -0
  91. package/src/apps/test/node_modules/.bin/tsserver +21 -0
  92. package/src/apps/test/node_modules/.bin/tsx +21 -0
  93. package/src/apps/test/node_modules/.bin/uuid +21 -0
  94. package/src/apps/test/package.json +35 -0
  95. package/src/apps/test/public/favicon.svg +7 -0
  96. package/src/apps/test/public/page.css +499 -0
  97. package/src/apps/test/public/page.js +417 -0
  98. package/src/apps/test/public/scenario-runner.js +450 -0
  99. package/src/apps/test/src/index.ts +9 -0
  100. package/src/apps/test/src/mcp.ts +192 -0
  101. package/src/apps/test/src/routes/trigger.ts +285 -0
  102. package/src/apps/test/src/services/scenario-broadcaster.ts +60 -0
  103. package/src/apps/test/src/services/scenario-manager.ts +361 -0
  104. package/src/apps/test/src/services/scenario-store.ts +145 -0
  105. package/src/apps/test/tsconfig.json +8 -0
  106. package/src/apps/vocabulary/.turbo/turbo-build.log +5 -0
  107. package/src/apps/vocabulary/.turbo/turbo-lint.log +25 -0
  108. package/src/apps/vocabulary/.turbo/turbo-typecheck.log +5 -0
  109. package/src/apps/vocabulary/mcp.ts +173 -0
  110. package/src/apps/vocabulary/node_modules/.bin/tsc +21 -0
  111. package/src/apps/vocabulary/node_modules/.bin/tsserver +21 -0
  112. package/src/apps/vocabulary/node_modules/.bin/tsx +21 -0
  113. package/src/apps/vocabulary/package.json +25 -0
  114. package/src/apps/vocabulary/public/page.css +247 -0
  115. package/src/apps/vocabulary/public/page.js +444 -0
  116. package/src/apps/vocabulary/services/vocabulary-store.ts +179 -0
  117. package/src/apps/vocabulary/src/index.ts +10 -0
  118. package/src/apps/vocabulary/tsconfig.json +8 -0
  119. package/src/apps/vocabulary/types.ts +22 -0
  120. package/src/apps/voice/.turbo/turbo-build.log +5 -0
  121. package/src/apps/voice/.turbo/turbo-lint.log +43 -0
  122. package/src/apps/voice/.turbo/turbo-typecheck.log +5 -0
  123. package/src/apps/voice/node_modules/.bin/openai +21 -0
  124. package/src/apps/voice/node_modules/.bin/tsc +21 -0
  125. package/src/apps/voice/node_modules/.bin/tsserver +21 -0
  126. package/src/apps/voice/node_modules/.bin/tsx +21 -0
  127. package/src/apps/voice/package.json +35 -0
  128. package/src/apps/voice/public/favicon.svg +7 -0
  129. package/src/apps/voice/public/page.css +388 -0
  130. package/src/apps/voice/public/page.js +718 -0
  131. package/src/apps/voice/src/index.ts +10 -0
  132. package/src/apps/voice/src/mcp.ts +70 -0
  133. package/src/apps/voice/src/providers/index.ts +85 -0
  134. package/src/apps/voice/src/providers/openai-compatible.ts +94 -0
  135. package/src/apps/voice/src/providers/types.ts +27 -0
  136. package/src/apps/voice/src/routes/config.ts +118 -0
  137. package/src/apps/voice/src/routes/transcribe.ts +90 -0
  138. package/src/apps/voice/src/services/config-store.ts +129 -0
  139. package/src/apps/voice/src/services/stats.ts +108 -0
  140. package/src/apps/voice/src/transcribe.ts +11 -0
  141. package/src/apps/voice/src/utils/mime.ts +16 -0
  142. package/src/apps/voice/tsconfig.json +8 -0
  143. package/src/apps/workflow/.turbo/turbo-build.log +5 -0
  144. package/src/apps/workflow/.turbo/turbo-lint.log +96 -0
  145. package/src/apps/workflow/.turbo/turbo-typecheck.log +5 -0
  146. package/src/apps/workflow/engine/executors/decision-executor.ts +87 -0
  147. package/src/apps/workflow/engine/executors/file-executor.ts +90 -0
  148. package/src/apps/workflow/engine/executors/git-executor.ts +137 -0
  149. package/src/apps/workflow/engine/executors/http-executor.ts +65 -0
  150. package/src/apps/workflow/engine/executors/index.ts +28 -0
  151. package/src/apps/workflow/engine/executors/kanban-executor.ts +154 -0
  152. package/src/apps/workflow/engine/executors/llm-executor.ts +46 -0
  153. package/src/apps/workflow/engine/executors/log-executor.ts +62 -0
  154. package/src/apps/workflow/engine/executors/loop-executor.ts +14 -0
  155. package/src/apps/workflow/engine/executors/shell-executor.ts +107 -0
  156. package/src/apps/workflow/engine/executors/sub-workflow-executor.ts +61 -0
  157. package/src/apps/workflow/engine/executors/test-executor.ts +73 -0
  158. package/src/apps/workflow/engine/executors/trigger-executor.ts +39 -0
  159. package/src/apps/workflow/engine/expression-evaluator.ts +117 -0
  160. package/src/apps/workflow/engine/graph-runner.ts +438 -0
  161. package/src/apps/workflow/engine/node-executor.ts +104 -0
  162. package/src/apps/workflow/engine/node-registry.ts +15 -0
  163. package/src/apps/workflow/engine/variable-resolver.ts +109 -0
  164. package/src/apps/workflow/mcp.ts +223 -0
  165. package/src/apps/workflow/node_modules/.bin/tsc +21 -0
  166. package/src/apps/workflow/node_modules/.bin/tsserver +21 -0
  167. package/src/apps/workflow/node_modules/.bin/tsx +21 -0
  168. package/src/apps/workflow/package.json +25 -0
  169. package/src/apps/workflow/public/editor/canvas.js +366 -0
  170. package/src/apps/workflow/public/editor/drag-manager.js +326 -0
  171. package/src/apps/workflow/public/editor/edge-renderer.js +235 -0
  172. package/src/apps/workflow/public/editor/history-manager.js +147 -0
  173. package/src/apps/workflow/public/editor/layout-engine.js +159 -0
  174. package/src/apps/workflow/public/editor/node-renderer.js +199 -0
  175. package/src/apps/workflow/public/editor/selection-manager.js +193 -0
  176. package/src/apps/workflow/public/favicon.svg +7 -0
  177. package/src/apps/workflow/public/models/node-types.js +300 -0
  178. package/src/apps/workflow/public/models/workflow-model.js +257 -0
  179. package/src/apps/workflow/public/page.css +406 -0
  180. package/src/apps/workflow/public/page.js +658 -0
  181. package/src/apps/workflow/public/panels/inspector.js +360 -0
  182. package/src/apps/workflow/public/panels/palette.js +106 -0
  183. package/src/apps/workflow/public/panels/run-view.js +275 -0
  184. package/src/apps/workflow/public/panels/toolbar.js +232 -0
  185. package/src/apps/workflow/public/panels/workflow-list.js +237 -0
  186. package/src/apps/workflow/public/state/store.js +47 -0
  187. package/src/apps/workflow/services/custom-node-loader.ts +48 -0
  188. package/src/apps/workflow/services/legacy-converter.ts +72 -0
  189. package/src/apps/workflow/services/run-manager.ts +190 -0
  190. package/src/apps/workflow/services/workflow-store.ts +424 -0
  191. package/src/apps/workflow/services/workflow-validator.test.ts +103 -0
  192. package/src/apps/workflow/services/workflow-validator.ts +98 -0
  193. package/src/apps/workflow/src/index.ts +10 -0
  194. package/src/apps/workflow/templates/ci-pipeline.json +18 -0
  195. package/src/apps/workflow/templates/code-review.json +22 -0
  196. package/src/apps/workflow/templates/kanban-testing.json +24 -0
  197. package/src/apps/workflow/tsconfig.json +8 -0
  198. package/src/apps/workflow/types.ts +268 -0
  199. package/src/packages/auth-middleware.ts +14 -0
  200. package/src/packages/design-tokens/.turbo/turbo-build.log +10 -0
  201. package/src/packages/design-tokens/STYLEGUIDE.md +414 -0
  202. package/src/packages/design-tokens/build.js +413 -0
  203. package/src/packages/design-tokens/demo/index.html +1367 -0
  204. package/src/packages/design-tokens/demo/proposition-a.html +717 -0
  205. package/src/packages/design-tokens/demo/proposition-b.html +1239 -0
  206. package/src/packages/design-tokens/demo/proposition-c.html +1049 -0
  207. package/src/packages/design-tokens/dist/tailwind-preset.js +115 -0
  208. package/src/packages/design-tokens/dist/tokens.css +345 -0
  209. package/src/packages/design-tokens/dist/tokens.d.ts +229 -0
  210. package/src/packages/design-tokens/dist/tokens.js +386 -0
  211. package/src/packages/design-tokens/package.json +25 -0
  212. package/src/packages/design-tokens/tokens.json +228 -0
  213. package/src/packages/devtools-middleware.ts +22 -0
  214. package/src/packages/eslint-config/index.js +63 -0
  215. package/src/packages/eslint-config/node_modules/.bin/eslint +21 -0
  216. package/src/packages/eslint-config/package.json +18 -0
  217. package/src/packages/json-file-store.ts +232 -0
  218. package/src/packages/mcp-utils/.turbo/turbo-build.log +5 -0
  219. package/src/packages/mcp-utils/dist/index.d.ts +33 -0
  220. package/src/packages/mcp-utils/dist/index.d.ts.map +1 -0
  221. package/src/packages/mcp-utils/dist/index.js +126 -0
  222. package/src/packages/mcp-utils/dist/index.js.map +1 -0
  223. package/src/packages/mcp-utils/node_modules/.bin/tsc +21 -0
  224. package/src/packages/mcp-utils/node_modules/.bin/tsserver +21 -0
  225. package/src/packages/mcp-utils/package.json +32 -0
  226. package/src/packages/mcp-utils/src/index.ts +171 -0
  227. package/src/packages/mcp-utils/tsconfig.json +9 -0
  228. package/src/packages/paths.ts +18 -0
  229. package/src/packages/project-context/index.js +55 -0
  230. package/src/packages/project-context/package.json +13 -0
  231. package/src/packages/project-store.ts +127 -0
  232. package/src/packages/server-sniffer.ts +132 -0
  233. package/src/packages/shared-assets/favicon.svg +7 -0
  234. package/src/packages/shared-assets/keymap-registry.js +512 -0
  235. package/src/packages/shared-assets/logo.svg +6 -0
  236. package/src/packages/shared-assets/package.json +11 -0
  237. package/src/packages/shared-assets/ui-utils.js +48 -0
  238. package/src/packages/shared-assets/voice-widget.d.ts +37 -0
  239. package/src/packages/shared-assets/voice-widget.js +695 -0
  240. package/src/packages/shared-types/.turbo/turbo-build.log +5 -0
  241. package/src/packages/shared-types/dist/index.d.ts +39 -0
  242. package/src/packages/shared-types/dist/index.d.ts.map +1 -0
  243. package/src/packages/shared-types/node_modules/.bin/tsc +21 -0
  244. package/src/packages/shared-types/node_modules/.bin/tsserver +21 -0
  245. package/src/packages/shared-types/package.json +25 -0
  246. package/src/packages/shared-types/src/index.ts +41 -0
  247. package/src/packages/shared-types/tsconfig.json +11 -0
  248. package/src/packages/tsconfig/base.json +15 -0
  249. package/src/packages/tsconfig/next.json +14 -0
  250. package/src/packages/tsconfig/node.json +11 -0
  251. package/src/packages/tsconfig/package.json +10 -0
  252. package/turbo.json +25 -0
@@ -0,0 +1,275 @@
1
+ @keyframes page-keymap-slide-up {
2
+ from { opacity: 0; transform: translateY(8px); }
3
+ to { opacity: 1; transform: translateY(0); }
4
+ }
5
+
6
+ @keyframes page-keymap-kbd-pulse {
7
+ 0%, 100% {
8
+ box-shadow:
9
+ 0 0 4px color-mix(in srgb, var(--df-color-accent-default) 30%, transparent),
10
+ inset 0 0 2px color-mix(in srgb, var(--df-color-accent-default) 10%, transparent);
11
+ border-color: var(--df-color-accent-default);
12
+ }
13
+ 50% {
14
+ box-shadow:
15
+ 0 0 14px color-mix(in srgb, var(--df-color-accent-default) 60%, transparent),
16
+ inset 0 0 6px color-mix(in srgb, var(--df-color-accent-default) 20%, transparent);
17
+ border-color: var(--df-color-accent-bright);
18
+ }
19
+ }
20
+
21
+ .page-keymap {
22
+ font-family: var(--df-font-mono);
23
+ background: var(--df-color-bg-base);
24
+ color: var(--df-color-text-primary);
25
+ -webkit-font-smoothing: antialiased;
26
+ font-size: var(--df-font-size-md);
27
+ min-height: 100vh;
28
+ line-height: 1.5;
29
+ }
30
+
31
+
32
+ /* ── Header (app-specific additions) ──────────────────────────────────── */
33
+ .page-keymap header {
34
+ flex-shrink: 0;
35
+ }
36
+
37
+ .page-keymap .toolbar-actions {
38
+ display: flex;
39
+ gap: var(--df-space-2);
40
+ }
41
+
42
+ /* ── Main layout ─────────────────────────────────────────────────────── */
43
+ .page-keymap main {
44
+ overflow-y: auto;
45
+ padding: var(--df-space-6) var(--df-space-4);
46
+ scrollbar-width: thin;
47
+ scrollbar-color: var(--df-color-border-default) transparent;
48
+ }
49
+
50
+ .page-keymap .shortcut-groups {
51
+ max-width: var(--df-max-width-md);
52
+ margin: 0 auto;
53
+ }
54
+
55
+ /* ── Buttons ──────────────────────────────────────────────────────────── */
56
+ .page-keymap .btn {
57
+ padding: var(--df-space-1) var(--df-space-3);
58
+ border: 1px solid var(--df-color-border-default);
59
+ background: var(--df-color-bg-raised);
60
+ color: var(--df-color-text-primary);
61
+ cursor: pointer;
62
+ font-family: var(--df-font-mono);
63
+ font-size: var(--df-font-size-xs);
64
+ letter-spacing: var(--df-letter-spacing-wide);
65
+ text-transform: uppercase;
66
+ clip-path: var(--df-clip-sm);
67
+ white-space: nowrap;
68
+ transition:
69
+ background var(--df-duration-fast) ease,
70
+ border-color var(--df-duration-fast) ease,
71
+ color var(--df-duration-fast) ease;
72
+ }
73
+
74
+ .page-keymap .btn:hover {
75
+ background: var(--df-color-bg-overlay);
76
+ border-color: var(--df-color-accent-default);
77
+ }
78
+
79
+ .page-keymap .btn:active {
80
+ background: color-mix(in srgb, var(--df-color-bg-raised) 70%, black);
81
+ }
82
+
83
+ .page-keymap .btn-sm {
84
+ padding: 3px 10px;
85
+ }
86
+
87
+ .page-keymap .btn-danger {
88
+ border-color: color-mix(in srgb, var(--df-color-state-error) 40%, transparent);
89
+ color: var(--df-color-state-error);
90
+ }
91
+
92
+ .page-keymap .btn-danger:hover {
93
+ border-color: var(--df-color-state-error);
94
+ background: color-mix(in srgb, var(--df-color-state-error) 12%, var(--df-color-bg-raised));
95
+ }
96
+
97
+ /* ── Shortcut groups ─────────────────────────────────────────────────── */
98
+ .page-keymap .shortcut-group {
99
+ margin-bottom: var(--df-space-4);
100
+ background: var(--df-color-bg-surface);
101
+ border: 1px solid var(--df-color-border-subtle);
102
+ clip-path: var(--df-clip-md);
103
+ overflow: hidden;
104
+ animation: page-keymap-slide-up var(--df-duration-base) var(--df-easing-default) both;
105
+ }
106
+
107
+ .page-keymap .group-title {
108
+ padding: var(--df-space-2) var(--df-space-4);
109
+ font-size: var(--df-font-size-xs);
110
+ font-weight: normal;
111
+ color: var(--df-color-text-muted);
112
+ letter-spacing: var(--df-letter-spacing-wider);
113
+ text-transform: uppercase;
114
+ background: var(--df-color-bg-raised);
115
+ border-bottom: 1px solid var(--df-color-border-subtle);
116
+ user-select: none;
117
+ }
118
+
119
+ /* ── Shortcut rows ───────────────────────────────────────────────────── */
120
+ .page-keymap .shortcut-row {
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: space-between;
124
+ flex-wrap: wrap;
125
+ padding: var(--df-space-2) var(--df-space-4);
126
+ border-bottom: 1px solid var(--df-color-border-subtle);
127
+ transition: background var(--df-duration-fast) ease;
128
+ }
129
+
130
+ .page-keymap .shortcut-row:last-child {
131
+ border-bottom: none;
132
+ }
133
+
134
+ .page-keymap .shortcut-row:hover {
135
+ background: color-mix(in srgb, var(--df-color-accent-default) 4%, transparent);
136
+ }
137
+
138
+ .page-keymap .shortcut-desc {
139
+ font-size: var(--df-font-size-sm);
140
+ color: var(--df-color-text-primary);
141
+ flex: 1;
142
+ min-width: 0;
143
+ overflow: hidden;
144
+ text-overflow: ellipsis;
145
+ white-space: nowrap;
146
+ margin-right: var(--df-space-3);
147
+ }
148
+
149
+ .page-keymap .shortcut-right {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: var(--df-space-2);
153
+ flex-shrink: 0;
154
+ }
155
+
156
+ /* ── Kbd element ─────────────────────────────────────────────────────── */
157
+ .page-keymap .shortcut-kbd {
158
+ display: inline-block;
159
+ min-width: 80px;
160
+ padding: 4px 10px;
161
+ background: color-mix(in srgb, var(--df-color-text-primary) 7%, transparent);
162
+ border: 1px solid color-mix(in srgb, var(--df-color-text-primary) 15%, transparent);
163
+ border-radius: var(--df-radius-sm);
164
+ color: var(--df-color-text-primary);
165
+ font-family: var(--df-font-mono);
166
+ font-size: var(--df-font-size-xs);
167
+ letter-spacing: var(--df-letter-spacing-normal);
168
+ text-align: center;
169
+ white-space: nowrap;
170
+ transition:
171
+ border-color var(--df-duration-fast) ease,
172
+ box-shadow var(--df-duration-fast) ease,
173
+ background var(--df-duration-fast) ease;
174
+ }
175
+
176
+ /* ── Recording state ─────────────────────────────────────────────────── */
177
+ .page-keymap .shortcut-kbd.recording {
178
+ border-color: var(--df-color-accent-default);
179
+ background: color-mix(in srgb, var(--df-color-accent-default) 10%, transparent);
180
+ color: var(--df-color-accent-default);
181
+ animation: page-keymap-kbd-pulse 1.2s ease-in-out infinite;
182
+ }
183
+
184
+ /* ── Conflict warning ────────────────────────────────────────────────── */
185
+ .page-keymap .conflict-warning {
186
+ width: 100%;
187
+ padding: var(--df-space-2) var(--df-space-4);
188
+ margin-top: var(--df-space-1);
189
+ font-size: var(--df-font-size-xs);
190
+ color: var(--df-primitive-amber-5);
191
+ background: color-mix(in srgb, var(--df-primitive-amber-3) 12%, transparent);
192
+ border-left: 3px solid var(--df-primitive-amber-4);
193
+ border-radius: 0 var(--df-radius-sm) var(--df-radius-sm) 0;
194
+ letter-spacing: var(--df-letter-spacing-normal);
195
+ animation: page-keymap-slide-up var(--df-duration-fast) var(--df-easing-default) both;
196
+ }
197
+
198
+ /* ── Empty state (overrides global .empty-state) ─────────────────────── */
199
+ .page-keymap .empty-state {
200
+ min-height: 200px;
201
+ gap: var(--df-space-2);
202
+ pointer-events: none;
203
+ }
204
+ .page-keymap .empty-state .hint {
205
+ font-size: 48px;
206
+ opacity: 0.15;
207
+ }
208
+ .page-keymap .empty-state .sub {
209
+ font-size: var(--df-font-size-sm);
210
+ letter-spacing: var(--df-letter-spacing-wide);
211
+ text-transform: uppercase;
212
+ }
213
+
214
+ /* ── Stagger animation for groups ────────────────────────────────────── */
215
+ .page-keymap .shortcut-group:nth-child(1) { animation-delay: 0ms; }
216
+ .page-keymap .shortcut-group:nth-child(2) { animation-delay: 60ms; }
217
+ .page-keymap .shortcut-group:nth-child(3) { animation-delay: 120ms; }
218
+ .page-keymap .shortcut-group:nth-child(4) { animation-delay: 180ms; }
219
+ .page-keymap .shortcut-group:nth-child(5) { animation-delay: 240ms; }
220
+ .page-keymap .shortcut-group:nth-child(6) { animation-delay: 300ms; }
221
+
222
+ /* ── Scrollbar ───────────────────────────────────────────────────────── */
223
+ .page-keymap ::-webkit-scrollbar { width: 8px; }
224
+ .page-keymap ::-webkit-scrollbar-track { background: transparent; }
225
+ .page-keymap ::-webkit-scrollbar-thumb { background: var(--df-color-border-default); border-radius: var(--df-radius-full); }
226
+ .page-keymap ::-webkit-scrollbar-thumb:hover { background: var(--df-color-border-strong); }
227
+
228
+ /* ── Reduced motion ──────────────────────────────────────────────────── */
229
+ @media (prefers-reduced-motion: reduce) {
230
+ .page-keymap .shortcut-kbd.recording { animation: none; box-shadow: var(--df-glow-accent); }
231
+ .page-keymap .shortcut-group { animation: none; }
232
+ .page-keymap .conflict-warning { animation: none; }
233
+ }
234
+
235
+ /* ── Mobile / narrow viewports ───────────────────────────────────────── */
236
+ @media (max-width: 639px) {
237
+ .page-keymap main {
238
+ padding: var(--df-space-3);
239
+ }
240
+
241
+ .page-keymap .toolbar-actions {
242
+ gap: var(--df-space-1);
243
+ }
244
+
245
+ .page-keymap .shortcut-row {
246
+ flex-direction: column;
247
+ align-items: flex-start;
248
+ gap: var(--df-space-2);
249
+ }
250
+
251
+ .page-keymap .shortcut-desc {
252
+ margin-right: 0;
253
+ white-space: normal;
254
+ }
255
+
256
+ .page-keymap .shortcut-right {
257
+ width: 100%;
258
+ justify-content: flex-start;
259
+ }
260
+
261
+ .page-keymap .shortcut-kbd {
262
+ min-width: 60px;
263
+ }
264
+ }
265
+
266
+ /* ── Large screens ───────────────────────────────────────────────────── */
267
+ @media (min-width: 1440px) {
268
+ .page-keymap .shortcut-groups {
269
+ max-width: var(--df-max-width-lg);
270
+ }
271
+
272
+ .page-keymap .shortcut-row {
273
+ padding: var(--df-space-3) var(--df-space-5);
274
+ }
275
+ }
@@ -0,0 +1,294 @@
1
+ // ── Keymap App — Page Module ─────────────────────────────────────────
2
+ // ES module that exports mount(container, ctx), unmount(container),
3
+ // and onProjectChange(project).
4
+
5
+ const MODIFIER_KEYS = new Set(['Control', 'Alt', 'Shift', 'Meta', 'CapsLock', 'NumLock', 'ScrollLock']);
6
+
7
+ let _container = null;
8
+ let _registry = null;
9
+ let _recordingState = null; // { actionId, kbdEl, editBtn, conflictEl, rowEl }
10
+ let _onRecordKeydown = null;
11
+ let _unsubRegistry = null;
12
+
13
+ // ── HTML ─────────────────────────────────────────────────────────────
14
+
15
+ const BODY_HTML = `
16
+ <header>
17
+ <div class="brand">Keymap</div>
18
+ <div class="toolbar-actions">
19
+ <button class="btn" id="km-btn-reset-all">Reset All</button>
20
+ <button class="btn" id="km-btn-export">Export</button>
21
+ <button class="btn" id="km-btn-import">Import</button>
22
+ <input type="file" id="km-file-input" accept=".json" style="display:none" />
23
+ </div>
24
+ </header>
25
+
26
+ <main>
27
+ <div class="shortcut-groups" id="km-shortcut-groups"></div>
28
+ </main>
29
+ `;
30
+
31
+ // ── Rendering ───────────────────────────────────────────────────────
32
+
33
+ function render() {
34
+ if (!_container || !_registry) return;
35
+
36
+ const groupsContainer = _container.querySelector('#km-shortcut-groups');
37
+ if (!groupsContainer) return;
38
+
39
+ const groups = _registry.getAll();
40
+ groupsContainer.innerHTML = '';
41
+
42
+ Object.keys(groups).forEach(groupName => {
43
+ const section = document.createElement('section');
44
+ section.className = 'shortcut-group';
45
+
46
+ const title = document.createElement('h2');
47
+ title.className = 'group-title';
48
+ title.textContent = groupName;
49
+ section.appendChild(title);
50
+
51
+ groups[groupName].forEach(item => {
52
+ section.appendChild(buildRow(item));
53
+ });
54
+
55
+ groupsContainer.appendChild(section);
56
+ });
57
+ }
58
+
59
+ function buildRow(item) {
60
+ const row = document.createElement('div');
61
+ row.className = 'shortcut-row';
62
+ row.dataset.actionId = item.actionId;
63
+
64
+ const desc = document.createElement('span');
65
+ desc.className = 'shortcut-desc';
66
+ desc.textContent = item.description || item.actionId;
67
+
68
+ const right = document.createElement('div');
69
+ right.className = 'shortcut-right';
70
+
71
+ const kbd = document.createElement('kbd');
72
+ kbd.className = 'shortcut-kbd';
73
+ kbd.textContent = _registry.formatBinding(item.binding);
74
+
75
+ const editBtn = document.createElement('button');
76
+ editBtn.className = 'btn btn-sm';
77
+ editBtn.textContent = 'Edit';
78
+
79
+ const resetBtn = document.createElement('button');
80
+ resetBtn.className = 'btn btn-sm btn-danger';
81
+ resetBtn.textContent = 'Reset';
82
+ resetBtn.style.display = item.overridden ? '' : 'none';
83
+
84
+ const conflictEl = document.createElement('div');
85
+ conflictEl.className = 'conflict-warning';
86
+ conflictEl.style.display = 'none';
87
+
88
+ editBtn.addEventListener('click', () => {
89
+ startRecording(item.actionId, kbd, editBtn, conflictEl, row);
90
+ });
91
+
92
+ resetBtn.addEventListener('click', () => {
93
+ _registry.reset(item.actionId);
94
+ kbd.textContent = _registry.formatBinding(_registry.getBinding(item.actionId));
95
+ resetBtn.style.display = 'none';
96
+ conflictEl.style.display = 'none';
97
+ });
98
+
99
+ right.appendChild(kbd);
100
+ right.appendChild(editBtn);
101
+ right.appendChild(resetBtn);
102
+
103
+ row.appendChild(desc);
104
+ row.appendChild(right);
105
+ row.appendChild(conflictEl);
106
+
107
+ row._refs = { kbd, editBtn, resetBtn, conflictEl };
108
+ return row;
109
+ }
110
+
111
+ // ── Recording ───────────────────────────────────────────────────────
112
+
113
+ function startRecording(actionId, kbdEl, editBtn, conflictEl, rowEl) {
114
+ cancelRecording();
115
+
116
+ kbdEl.classList.add('recording');
117
+ kbdEl.textContent = 'Press keys\u2026';
118
+ editBtn.textContent = 'Cancel';
119
+
120
+ _recordingState = { actionId, kbdEl, editBtn, conflictEl, rowEl };
121
+
122
+ editBtn.onclick = () => cancelRecording();
123
+
124
+ _onRecordKeydown = (e) => {
125
+ if (e.key === 'Escape') {
126
+ e.preventDefault();
127
+ e.stopImmediatePropagation();
128
+ cancelRecording();
129
+ return;
130
+ }
131
+
132
+ if (MODIFIER_KEYS.has(e.key)) return;
133
+
134
+ e.preventDefault();
135
+ e.stopImmediatePropagation();
136
+
137
+ const newBinding = _registry.captureBinding(e);
138
+ const { actionId: aid, kbdEl: kEl, editBtn: eBtn, conflictEl: cEl, rowEl: rEl } = _recordingState;
139
+
140
+ // Check conflicts
141
+ const groups = _registry.getAll();
142
+ let conflict = null;
143
+ const newFormatted = _registry.formatBinding(newBinding);
144
+ Object.values(groups).flat().forEach(item => {
145
+ if (item.actionId !== aid && _registry.formatBinding(item.binding) === newFormatted) {
146
+ conflict = item;
147
+ }
148
+ });
149
+
150
+ _registry.rebind(aid, newBinding);
151
+
152
+ if (conflict) {
153
+ cEl.textContent = 'Conflicts with: ' + (conflict.description || conflict.actionId);
154
+ cEl.style.display = '';
155
+ } else {
156
+ cEl.style.display = 'none';
157
+ }
158
+
159
+ finishRecording();
160
+ kEl.textContent = _registry.formatBinding(newBinding);
161
+ rEl._refs.resetBtn.style.display = '';
162
+ };
163
+
164
+ document.addEventListener('keydown', _onRecordKeydown, true);
165
+ }
166
+
167
+ function cancelRecording() {
168
+ if (!_recordingState) return;
169
+ const { actionId, kbdEl } = _recordingState;
170
+ const binding = _registry.getBinding(actionId);
171
+ kbdEl.textContent = binding ? _registry.formatBinding(binding) : 'None';
172
+ finishRecording();
173
+ }
174
+
175
+ function finishRecording() {
176
+ if (!_recordingState) return;
177
+ const { kbdEl, editBtn, actionId } = _recordingState;
178
+ kbdEl.classList.remove('recording');
179
+ editBtn.textContent = 'Edit';
180
+
181
+ if (_onRecordKeydown) {
182
+ document.removeEventListener('keydown', _onRecordKeydown, true);
183
+ _onRecordKeydown = null;
184
+ }
185
+
186
+ // Re-bind edit button properly
187
+ const row = _recordingState.rowEl;
188
+ const refs = row._refs;
189
+ editBtn.onclick = () => startRecording(actionId, refs.kbd, refs.editBtn, refs.conflictEl, row);
190
+
191
+ _recordingState = null;
192
+ }
193
+
194
+ // ── Header button handlers ──────────────────────────────────────────
195
+
196
+ function bindToolbarActions() {
197
+ if (!_container) return;
198
+
199
+ _container.querySelector('#km-btn-reset-all').addEventListener('click', () => {
200
+ _registry.resetAll();
201
+ render();
202
+ });
203
+
204
+ _container.querySelector('#km-btn-export').addEventListener('click', () => {
205
+ const json = _registry.exportConfig();
206
+ const blob = new Blob([json], { type: 'application/json' });
207
+ const url = URL.createObjectURL(blob);
208
+ const a = document.createElement('a');
209
+ a.href = url;
210
+ a.download = 'devglide-keybindings.json';
211
+ document.body.appendChild(a);
212
+ a.click();
213
+ document.body.removeChild(a);
214
+ URL.revokeObjectURL(url);
215
+ });
216
+
217
+ const fileInput = _container.querySelector('#km-file-input');
218
+ _container.querySelector('#km-btn-import').addEventListener('click', () => fileInput.click());
219
+ fileInput.addEventListener('change', () => {
220
+ const file = fileInput.files?.[0];
221
+ if (!file) return;
222
+ const reader = new FileReader();
223
+ reader.onload = () => {
224
+ try {
225
+ _registry.importConfig(reader.result);
226
+ render();
227
+ } catch (err) {
228
+ console.error('Keymap import failed:', err);
229
+ }
230
+ };
231
+ reader.readAsText(file);
232
+ fileInput.value = '';
233
+ });
234
+ }
235
+
236
+ // ── Exports ─────────────────────────────────────────────────────────
237
+
238
+ export function mount(container, ctx) {
239
+ _container = container;
240
+ _registry = typeof KeymapRegistry !== 'undefined' ? KeymapRegistry : null;
241
+
242
+ // 1. Scope the container
243
+ container.classList.add('page-keymap');
244
+
245
+ // 2. Build HTML
246
+ container.innerHTML = BODY_HTML;
247
+
248
+ if (!_registry) {
249
+ container.querySelector('#km-shortcut-groups').innerHTML =
250
+ '<p class="empty-state">KeymapRegistry not loaded.</p>';
251
+ return;
252
+ }
253
+
254
+ // 3. Bind toolbar buttons
255
+ bindToolbarActions();
256
+
257
+ // 4. Initial render
258
+ render();
259
+
260
+ // 5. Listen for external binding changes
261
+ _unsubRegistry = _registry.onChange(() => {
262
+ if (!_recordingState) render();
263
+ });
264
+ }
265
+
266
+ export function unmount(container) {
267
+ // 1. Cancel any active recording
268
+ cancelRecording();
269
+
270
+ // 2. Unsubscribe from registry changes
271
+ if (_unsubRegistry) {
272
+ _unsubRegistry();
273
+ _unsubRegistry = null;
274
+ }
275
+
276
+ // 3. Remove keydown listener if still active
277
+ if (_onRecordKeydown) {
278
+ document.removeEventListener('keydown', _onRecordKeydown, true);
279
+ _onRecordKeydown = null;
280
+ }
281
+
282
+ // 4. Remove scope class & clear HTML
283
+ container.classList.remove('page-keymap');
284
+ container.innerHTML = '';
285
+
286
+ // 5. Clear module references
287
+ _container = null;
288
+ _registry = null;
289
+ _recordingState = null;
290
+ }
291
+
292
+ export function onProjectChange(project) {
293
+ // Keymap app is project-agnostic — no action needed
294
+ }
@@ -0,0 +1,25 @@
1
+ import express from 'express';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ const app = express();
8
+ const PORT = parseInt(process.env.PORT || '7008', 10);
9
+
10
+ app.use(express.static(path.join(__dirname, 'public')));
11
+ app.use('/shared-assets', express.static(path.join(__dirname, '../../packages/shared-assets')));
12
+ app.use('/design-tokens', express.static(path.join(__dirname, '../../packages/design-tokens/dist')));
13
+
14
+ const server = app.listen(PORT, () => {
15
+ console.log(`Devglide Keymap running at http://localhost:${PORT}`);
16
+ });
17
+
18
+ function shutdown() {
19
+ console.log('\nShutting down...');
20
+ server.close(() => process.exit(0));
21
+ setTimeout(() => process.exit(0), 2000);
22
+ }
23
+
24
+ process.on('SIGTERM', shutdown);
25
+ process.on('SIGINT', shutdown);
@@ -0,0 +1,5 @@
1
+  WARN  Issue while reading "/home/runner/_work/devglide/devglide/.npmrc". Failed to replace env in config: ${NODE_AUTH_TOKEN}
2
+
3
+ > @devglide/log@0.1.0 build /home/runner/_work/devglide/devglide/src/apps/log
4
+ > tsc
5
+
@@ -0,0 +1,45 @@
1
+  WARN  Issue while reading "/home/runner/_work/devglide/devglide/.npmrc". Failed to replace env in config: ${NODE_AUTH_TOKEN}
2
+
3
+ > @devglide/log@0.1.0 lint /home/runner/_work/devglide/devglide/src/apps/log
4
+ > eslint .
5
+
6
+
7
+ /home/runner/_work/devglide/devglide/src/apps/log/src/index.ts
8
+ 1:1 warning There should be at least one empty line between import groups import/order
9
+ 2:1 warning `@devglide/mcp-utils` import should occur before import of `./mcp.js` import/order
10
+
11
+ /home/runner/_work/devglide/devglide/src/apps/log/src/mcp.ts
12
+ 1:1 warning There should be at least one empty line between import groups import/order
13
+ 1:1 warning `zod` import should occur after import of `path` import/order
14
+ 3:1 warning There should be at least one empty line between import groups import/order
15
+ 4:1 warning There should be at least one empty line between import groups import/order
16
+ 5:1 warning `./services/log-writer.js` import should occur after import of `../../../packages/paths.js` import/order
17
+ 6:1 warning There should be at least one empty line between import groups import/order
18
+ 6:1 warning `./routes/log.js` import should occur after import of `../../../packages/paths.js` import/order
19
+
20
+ /home/runner/_work/devglide/devglide/src/apps/log/src/routes/log.ts
21
+ 2:1 warning There should be at least one empty line between import groups import/order
22
+ 3:1 warning `fs/promises` import should occur before import of `express` import/order
23
+ 4:1 warning There should be at least one empty line between import groups import/order
24
+ 4:1 warning `path` import should occur before import of `express` import/order
25
+ 6:1 warning `../../../../packages/paths.js` import should occur before import of `../services/log-writer.js` import/order
26
+
27
+ /home/runner/_work/devglide/devglide/src/apps/log/src/routes/status.ts
28
+ 2:1 warning There should be at least one empty line between import groups import/order
29
+ 3:1 warning There should be at least one empty line between import groups import/order
30
+ 4:1 warning `../../../../project-context.js` import should occur before import of `./log.js` import/order
31
+
32
+ /home/runner/_work/devglide/devglide/src/apps/log/src/services/file-tailer.ts
33
+ 1:1 warning There should be at least one empty line between import groups import/order
34
+ 1:1 warning `chokidar` import should occur after import of `crypto` import/order
35
+ 2:1 warning `fs/promises` import should occur after import of `crypto` import/order
36
+ 3:1 warning `path` import should occur after import of `crypto` import/order
37
+ 4:1 warning There should be at least one empty line between import groups import/order
38
+ 5:1 warning `./log-writer.js` import should occur after import of `./file-patterns.js` import/order
39
+ 6:1 warning There should be at least one empty line between import groups import/order
40
+ 6:1 warning `./line-parser.js` import should occur after import of `./file-patterns.js` import/order
41
+ 7:1 warning There should be at least one empty line between import groups import/order
42
+
43
+ ✖ 26 problems (0 errors, 26 warnings)
44
+ 0 errors and 26 warnings potentially fixable with the `--fix` option.
45
+
@@ -0,0 +1,5 @@
1
+  WARN  Issue while reading "/home/runner/_work/devglide/devglide/.npmrc". Failed to replace env in config: ${NODE_AUTH_TOKEN}
2
+
3
+ > @devglide/log@0.1.0 typecheck /home/runner/_work/devglide/devglide/src/apps/log
4
+ > tsc --noEmit
5
+
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/_work/devglide/devglide/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/_work/devglide/devglide/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/_work/devglide/devglide/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/_work/devglide/devglide/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/runner/_work/devglide/devglide/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/runner/_work/devglide/devglide/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
+ fi