@polderlabs/openkan 0.4.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 (114) hide show
  1. package/CHANGELOG.md +226 -0
  2. package/LICENSE +21 -0
  3. package/README.md +318 -0
  4. package/agents/openkan.md +254 -0
  5. package/bin/install-agent.mjs +63 -0
  6. package/bin/ok.mjs +17 -0
  7. package/bin/openkan.mjs +10 -0
  8. package/dist/.claude/skills/ok-planning/SKILL.md +285 -0
  9. package/dist/.claude/skills/ok-planning/references/integration.md +153 -0
  10. package/dist/.claude/skills/ok-planning/references/schemas.md +270 -0
  11. package/dist/.claude/skills/ok-planning/references/workflows.md +185 -0
  12. package/dist/.claude/skills/ok-planning/scripts/ok-init.sh +14 -0
  13. package/dist/.claude/skills/ok-planning/scripts/ok-resume.sh +38 -0
  14. package/dist/.claude/skills/ok-planning/scripts/ok-status.sh +24 -0
  15. package/dist/agents/openkan.md +254 -0
  16. package/dist/bin/install-agent.mjs +76 -0
  17. package/dist/bin/ok-install.js +58 -0
  18. package/dist/bin/ok.js +138 -0
  19. package/dist/bin/openkan.js +804 -0
  20. package/dist/commands/organize.md +15 -0
  21. package/dist/kanban/agent-profile.js +8 -0
  22. package/dist/kanban/archive.js +49 -0
  23. package/dist/kanban/bizar.js +242 -0
  24. package/dist/kanban/board.js +367 -0
  25. package/dist/kanban/bulk.js +139 -0
  26. package/dist/kanban/changelog.js +186 -0
  27. package/dist/kanban/chat.js +1280 -0
  28. package/dist/kanban/claude-state.js +974 -0
  29. package/dist/kanban/comments.js +80 -0
  30. package/dist/kanban/docs.js +144 -0
  31. package/dist/kanban/fs.js +163 -0
  32. package/dist/kanban/git.js +196 -0
  33. package/dist/kanban/images.js +140 -0
  34. package/dist/kanban/import.js +295 -0
  35. package/dist/kanban/inputs.js +94 -0
  36. package/dist/kanban/insights.js +140 -0
  37. package/dist/kanban/io.js +75 -0
  38. package/dist/kanban/mdx-render.js +348 -0
  39. package/dist/kanban/mdx.js +231 -0
  40. package/dist/kanban/projects.js +545 -0
  41. package/dist/kanban/search.js +121 -0
  42. package/dist/kanban/server.js +3296 -0
  43. package/dist/kanban/tags.js +124 -0
  44. package/dist/kanban/template.js +145 -0
  45. package/dist/kanban/tsx-sandbox.js +187 -0
  46. package/dist/kanban/watcher.js +270 -0
  47. package/dist/ok/commands/goal.js +65 -0
  48. package/dist/ok/commands/index.js +87 -0
  49. package/dist/ok/commands/init.js +15 -0
  50. package/dist/ok/commands/plan.js +155 -0
  51. package/dist/ok/commands/prd.js +202 -0
  52. package/dist/ok/commands/progress.js +31 -0
  53. package/dist/ok/commands/task.js +377 -0
  54. package/dist/ok/ids.js +98 -0
  55. package/dist/ok/lock.js +156 -0
  56. package/dist/ok/migrate.js +197 -0
  57. package/dist/ok/schemas.js +402 -0
  58. package/dist/ok/storage.js +222 -0
  59. package/dist/skills/openkan/SKILL.md +111 -0
  60. package/dist/skills/openkan/agents/openai.yaml +4 -0
  61. package/dist/skills/openkan/examples/simple-task.mdx +34 -0
  62. package/dist/skills/openkan/examples/with-ask.mdx +32 -0
  63. package/dist/skills/openkan/examples/with-choice.mdx +51 -0
  64. package/dist/skills/openkan/examples/with-preview.mdx +54 -0
  65. package/dist/skills/openkan/references/api.md +169 -0
  66. package/dist/skills/openkan/templates/task.mdx +46 -0
  67. package/dist/web/api.js +257 -0
  68. package/dist/web/app.js +4251 -0
  69. package/dist/web/bizar.js +39 -0
  70. package/dist/web/brand/agent-activity-sprite.svg +1 -0
  71. package/dist/web/brand/banner-docs.svg +24 -0
  72. package/dist/web/brand/banner.svg +32 -0
  73. package/dist/web/brand/empty-sessions.svg +17 -0
  74. package/dist/web/brand/empty-tasks.svg +17 -0
  75. package/dist/web/brand/favicon.svg +9 -0
  76. package/dist/web/brand/infinity-loader-animated.svg +220 -0
  77. package/dist/web/brand/infinity-loader-spritesheet.svg +230 -0
  78. package/dist/web/brand/logo-wordmark.svg +10 -0
  79. package/dist/web/brand/logo.svg +9 -0
  80. package/dist/web/brand/pixel-infinity-track.svg +1 -0
  81. package/dist/web/brand/social-card.svg +26 -0
  82. package/dist/web/changelog-view.js +456 -0
  83. package/dist/web/charts.js +269 -0
  84. package/dist/web/chat-sidebar.js +2397 -0
  85. package/dist/web/chat-status-motion.js +154 -0
  86. package/dist/web/claude-pane.js +820 -0
  87. package/dist/web/command-palette.js +381 -0
  88. package/dist/web/contributors-view.js +317 -0
  89. package/dist/web/cross-tab.js +102 -0
  90. package/dist/web/docs-view.js +168 -0
  91. package/dist/web/experience.css +165 -0
  92. package/dist/web/goals-view.js +45 -0
  93. package/dist/web/home-view.js +113 -0
  94. package/dist/web/images.js +311 -0
  95. package/dist/web/index.html +485 -0
  96. package/dist/web/insights.js +217 -0
  97. package/dist/web/keyboard.js +446 -0
  98. package/dist/web/mdx-viewer.js +600 -0
  99. package/dist/web/path-picker.js +787 -0
  100. package/dist/web/preview-frame.html +187 -0
  101. package/dist/web/settings.js +582 -0
  102. package/dist/web/style.css +8545 -0
  103. package/dist/web/task-view.js +1759 -0
  104. package/dist/web/vendor/gsap.min.js +11 -0
  105. package/dist/web/workspace.css +1513 -0
  106. package/package.json +71 -0
  107. package/skills/openkan/SKILL.md +111 -0
  108. package/skills/openkan/agents/openai.yaml +4 -0
  109. package/skills/openkan/examples/simple-task.mdx +34 -0
  110. package/skills/openkan/examples/with-ask.mdx +32 -0
  111. package/skills/openkan/examples/with-choice.mdx +51 -0
  112. package/skills/openkan/examples/with-preview.mdx +54 -0
  113. package/skills/openkan/references/api.md +169 -0
  114. package/skills/openkan/templates/task.mdx +46 -0
@@ -0,0 +1,154 @@
1
+ // OpenKan chat status motion — pixel-first GSAP cues. Live work loops with a
2
+ // distinct rhythm; terminal states run once, clear their timeline, and settle.
3
+ (() => {
4
+ "use strict";
5
+
6
+ const MODES = Object.freeze({
7
+ thinking: { label: "Thinking", cells: 8 },
8
+ searching: { label: "Searching the web", cells: 7 },
9
+ reading: { label: "Reading", cells: 6 },
10
+ command: { label: "Running command", cells: 7 },
11
+ editing: { label: "Editing", cells: 7 },
12
+ agent: { label: "Delegating", cells: 5 },
13
+ orchestration: { label: "Coordinating", cells: 5 },
14
+ mcp: { label: "Calling MCP", cells: 6 },
15
+ writing: { label: "Writing response", cells: 3 },
16
+ // A compact eight-point pixel flare: completion is a resolved signal,
17
+ // not a checkmark and never an idle loader.
18
+ complete: { label: "Completed", cells: 8 },
19
+ error: { label: "Needs attention", cells: 5 },
20
+ });
21
+
22
+ function modeFor(status = {}) {
23
+ const value = `${status.phase || ""} ${status.label || ""} ${status.name || ""}`.toLowerCase();
24
+ if (/(error|failed|denied|cancel)/.test(value)) return "error";
25
+ if (/(complete|finished|done|success)/.test(value)) return "complete";
26
+ if (/(mcp)/.test(value)) return "mcp";
27
+ if (/(team|workflow|orchestrat)/.test(value)) return "orchestration";
28
+ if (/(subagent|delegat|agent)/.test(value)) return "agent";
29
+ if (/(websearch|searching the web|search the web)/.test(value)) return "searching";
30
+ if (/(read|search|find|fetch|glob|grep)/.test(value)) return "reading";
31
+ if (/(write|edit|patch|save)/.test(value)) return "editing";
32
+ if (/(bash|command|run(?:ning)?|terminal|exec)/.test(value)) return "command";
33
+ if (/(respond|stream|writing response)/.test(value)) return "writing";
34
+ return "thinking";
35
+ }
36
+
37
+ function markup(status = {}) {
38
+ const mode = modeFor(status);
39
+ const config = MODES[mode];
40
+ const pixels = Array.from({ length: config.cells }, (_, index) => `<i class="chat-status-motion__pixel chat-status-motion__pixel--${index}" aria-hidden="true"></i>`).join("");
41
+ return `<span class="chat-status-motion chat-status-motion--${mode}" data-chat-status-motion="${mode}" role="img" aria-label="${config.label}"><span class="chat-status-motion__pixels">${pixels}</span></span>`;
42
+ }
43
+
44
+ function stop(node) {
45
+ if (!node) return;
46
+ const timeline = node._chatStatusTimeline;
47
+ if (timeline) timeline.kill();
48
+ const gsap = window.gsap;
49
+ const pixels = [...node.querySelectorAll?.(".chat-status-motion__pixel") || []];
50
+ gsap?.killTweensOf?.(pixels);
51
+ delete node._chatStatusTimeline;
52
+ delete node.dataset.chatStatusAnimating;
53
+ }
54
+
55
+ function reducedMotion() {
56
+ return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
57
+ }
58
+
59
+ function animate(node) {
60
+ if (!node) return;
61
+ stop(node);
62
+ const gsap = window.gsap;
63
+ const mode = node.dataset.chatStatusMotion || "thinking";
64
+ const pixels = [...node.querySelectorAll(".chat-status-motion__pixel")];
65
+ const terminal = mode === "complete" || mode === "error";
66
+ if (!gsap || !pixels.length || reducedMotion()) {
67
+ gsap?.set?.(pixels, { autoAlpha: 1, x: 0, y: 0, scale: 1, scaleY: 1, rotation: 0 });
68
+ if (terminal) node.dataset.chatStatusSettled = "true";
69
+ return;
70
+ }
71
+
72
+ delete node.dataset.chatStatusSettled;
73
+ if (terminal) node.dataset.chatStatusAnimating = "true";
74
+ gsap.set(pixels, { autoAlpha: 0.26, x: 0, y: 0, scale: 0.9, scaleY: 1, rotation: 0, transformOrigin: "50% 50%" });
75
+ // Only live states repeat. Terminal status always owns a finite timeline.
76
+ const tl = gsap.timeline({ repeat: terminal ? 0 : -1, defaults: { ease: "sine.inOut" } });
77
+ const even = pixels.filter((_, index) => index % 2 === 0);
78
+ const odd = pixels.filter((_, index) => index % 2 === 1);
79
+
80
+ switch (mode) {
81
+ case "thinking":
82
+ tl.to(pixels, { autoAlpha: 0.66, scale: 1, duration: 0.22, stagger: { each: 0.05, from: "center" } })
83
+ .to(even, { autoAlpha: 1, y: -2, scale: 1.2, duration: 0.24, stagger: { each: 0.075, from: "center" } }, "<.05")
84
+ .to(odd, { autoAlpha: 0.9, y: 2, scale: 1.1, duration: 0.24, stagger: { each: 0.075, from: "center" } }, "<")
85
+ .to(pixels, { autoAlpha: 0.3, x: 0, y: 0, scale: 0.9, duration: 0.34, stagger: { each: 0.04, from: "edges" } });
86
+ break;
87
+ case "reading":
88
+ tl.to(pixels, { autoAlpha: 0.36, duration: 0.1 })
89
+ .to(pixels, { autoAlpha: 1, scaleY: 1.45, duration: 0.14, stagger: { each: 0.065, from: "start" } })
90
+ .to(pixels, { autoAlpha: 0.32, scaleY: 0.92, duration: 0.16, stagger: { each: 0.065, from: "end" } });
91
+ break;
92
+ case "searching":
93
+ tl.to(pixels, { autoAlpha: 0.3, scale: 0.82, duration: 0.12 })
94
+ .to(pixels, { autoAlpha: 1, scale: 1.2, duration: 0.17, stagger: { each: 0.07, from: "center" } })
95
+ .to(pixels, { autoAlpha: 0.36, scale: 0.92, duration: 0.2, stagger: { each: 0.07, from: "edges" } });
96
+ break;
97
+ case "command":
98
+ tl.to(pixels, { autoAlpha: 0.34, duration: 0.1 })
99
+ .to(pixels, { autoAlpha: 1, x: 2, duration: 0.1, stagger: { each: 0.05, from: "start" } })
100
+ .to(pixels, { autoAlpha: 0.42, x: 0, duration: 0.13, stagger: { each: 0.05, from: "end" } });
101
+ break;
102
+ case "editing":
103
+ tl.to(pixels, { autoAlpha: 1, rotation: -24, y: -2, scale: 1.14, duration: 0.19, stagger: { each: 0.055, from: "start" } })
104
+ .to(pixels, { autoAlpha: 0.3, rotation: 0, y: 1, scale: 0.88, duration: 0.26, stagger: { each: 0.055, from: "end" } });
105
+ break;
106
+ case "agent":
107
+ tl.to(pixels, { autoAlpha: 1, scale: 1.28, duration: 0.23, stagger: { each: 0.085, from: "center" } })
108
+ .to(pixels, { autoAlpha: 0.35, scale: 0.76, duration: 0.28, stagger: { each: 0.085, from: "edges" } });
109
+ break;
110
+ case "orchestration":
111
+ tl.to(even, { autoAlpha: 1, x: 2, y: -1, duration: 0.19, stagger: { each: 0.09, from: "start" } })
112
+ .to(odd, { autoAlpha: 1, x: -2, y: 1, duration: 0.19, stagger: { each: 0.09, from: "end" } }, "<")
113
+ .to(pixels, { autoAlpha: 0.3, x: 0, y: 0, duration: 0.26 });
114
+ break;
115
+ case "mcp":
116
+ tl.to(even, { autoAlpha: 1, scale: 1.24, duration: 0.17 })
117
+ .to(odd, { autoAlpha: 1, scale: 1.24, duration: 0.17 }, "<.11")
118
+ .to(pixels, { autoAlpha: 0.32, scale: 0.86, duration: 0.22 });
119
+ break;
120
+ case "writing":
121
+ tl.to(pixels, { autoAlpha: 1, y: -2, scale: 1.2, duration: 0.19, stagger: { each: 0.11, from: "start" } })
122
+ .to(pixels, { autoAlpha: 0.34, y: 1, scale: 0.9, duration: 0.26, stagger: { each: 0.11, from: "end" } });
123
+ break;
124
+ case "complete": {
125
+ const points = [pixels[0], pixels[2], pixels[4], pixels[6]].filter(Boolean);
126
+ const diagonals = [pixels[1], pixels[3], pixels[5], pixels[7]].filter(Boolean);
127
+ tl.to(points, { autoAlpha: 1, scale: 1.35, duration: 0.12, stagger: { each: 0.055, from: "center" } })
128
+ .to(diagonals, { autoAlpha: 0.9, scale: 1.12, duration: 0.12, stagger: { each: 0.045, from: "center" } }, "<.045")
129
+ .to(pixels, { autoAlpha: 1, x: 0, y: 0, scale: 1, scaleY: 1, rotation: 0, duration: 0.2, stagger: { each: 0.018, from: "center" } });
130
+ break;
131
+ }
132
+ case "error":
133
+ tl.to(pixels, { autoAlpha: 1, x: -2, duration: 0.09 })
134
+ .to(pixels, { x: 2, duration: 0.12, repeat: 2, yoyo: true })
135
+ .set(pixels, { autoAlpha: 1, x: 0, y: 0, scale: 1, scaleY: 1 });
136
+ break;
137
+ }
138
+
139
+ node._chatStatusTimeline = tl;
140
+ if (terminal) {
141
+ tl.eventCallback("onComplete", () => {
142
+ gsap.killTweensOf(pixels);
143
+ gsap.set(pixels, { autoAlpha: 1, x: 0, y: 0, scale: 1, scaleY: 1, rotation: 0 });
144
+ delete node.dataset.chatStatusAnimating;
145
+ node.dataset.chatStatusSettled = "true";
146
+ if (node._chatStatusTimeline === tl) delete node._chatStatusTimeline;
147
+ });
148
+ }
149
+ }
150
+
151
+ function render(status = {}) { return markup(status); }
152
+ function animateWithin(root) { root?.querySelectorAll?.("[data-chat-status-motion]").forEach(animate); }
153
+ window.OpenKanChatMotion = { render, animate, animateWithin, stop, modeFor };
154
+ })();