cf-claw 3.0.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 (273) hide show
  1. package/dist/agent.d.ts +15 -0
  2. package/dist/agent.d.ts.map +1 -0
  3. package/dist/agent.js +262 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/agents.d.ts +51 -0
  6. package/dist/agents.d.ts.map +1 -0
  7. package/dist/agents.js +478 -0
  8. package/dist/agents.js.map +1 -0
  9. package/dist/api/routes.d.ts +3 -0
  10. package/dist/api/routes.d.ts.map +1 -0
  11. package/dist/api/routes.js +491 -0
  12. package/dist/api/routes.js.map +1 -0
  13. package/dist/bot.d.ts +4 -0
  14. package/dist/bot.d.ts.map +1 -0
  15. package/dist/bot.js +295 -0
  16. package/dist/bot.js.map +1 -0
  17. package/dist/canvas.d.ts +37 -0
  18. package/dist/canvas.d.ts.map +1 -0
  19. package/dist/canvas.js +47 -0
  20. package/dist/canvas.js.map +1 -0
  21. package/dist/cli.d.ts +3 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +202 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/commands.d.ts +6 -0
  26. package/dist/commands.d.ts.map +1 -0
  27. package/dist/commands.js +384 -0
  28. package/dist/commands.js.map +1 -0
  29. package/dist/components/TaskList.d.ts +7 -0
  30. package/dist/components/TaskList.d.ts.map +1 -0
  31. package/dist/components/TaskList.js +37 -0
  32. package/dist/components/TaskList.js.map +1 -0
  33. package/dist/config/encryption.d.ts +10 -0
  34. package/dist/config/encryption.d.ts.map +1 -0
  35. package/dist/config/encryption.js +111 -0
  36. package/dist/config/encryption.js.map +1 -0
  37. package/dist/config/json-config.d.ts +114 -0
  38. package/dist/config/json-config.d.ts.map +1 -0
  39. package/dist/config/json-config.js +388 -0
  40. package/dist/config/json-config.js.map +1 -0
  41. package/dist/config.d.ts +51 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +137 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/context/pruning.d.ts +30 -0
  46. package/dist/context/pruning.d.ts.map +1 -0
  47. package/dist/context/pruning.js +132 -0
  48. package/dist/context/pruning.js.map +1 -0
  49. package/dist/dashboard/404/index.html +1 -0
  50. package/dist/dashboard/404.html +1 -0
  51. package/dist/dashboard/_next/static/chunks/117-c657912d4a6fa056.js +2 -0
  52. package/dist/dashboard/_next/static/chunks/191-a6922264096cb3ad.js +11 -0
  53. package/dist/dashboard/_next/static/chunks/343-71498a8257bc1e81.js +1 -0
  54. package/dist/dashboard/_next/static/chunks/app/_not-found/page-15cbe4395e02a084.js +1 -0
  55. package/dist/dashboard/_next/static/chunks/app/layout-191efbc962809bb4.js +1 -0
  56. package/dist/dashboard/_next/static/chunks/app/manual/page-3c401ecf89979cd7.js +1 -0
  57. package/dist/dashboard/_next/static/chunks/app/page-dff55e58941a3c4d.js +1 -0
  58. package/dist/dashboard/_next/static/chunks/fd9d1056-9583fa19bc194043.js +1 -0
  59. package/dist/dashboard/_next/static/chunks/framework-f66176bb897dc684.js +1 -0
  60. package/dist/dashboard/_next/static/chunks/main-2461f93106bcf687.js +1 -0
  61. package/dist/dashboard/_next/static/chunks/main-app-89f5ec28b3bb0e7f.js +1 -0
  62. package/dist/dashboard/_next/static/chunks/pages/_app-72b849fbd24ac258.js +1 -0
  63. package/dist/dashboard/_next/static/chunks/pages/_error-7ba65e1336b92748.js +1 -0
  64. package/dist/dashboard/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  65. package/dist/dashboard/_next/static/chunks/webpack-616e068a201ad621.js +1 -0
  66. package/dist/dashboard/_next/static/css/baff0f221c10680b.css +3 -0
  67. package/dist/dashboard/_next/static/pyqPyo6dkz4uTWdfdFAOJ/_buildManifest.js +1 -0
  68. package/dist/dashboard/_next/static/pyqPyo6dkz4uTWdfdFAOJ/_ssgManifest.js +1 -0
  69. package/dist/dashboard/index.html +1 -0
  70. package/dist/dashboard/index.txt +7 -0
  71. package/dist/dashboard/manual/index.html +1 -0
  72. package/dist/dashboard/manual/index.txt +7 -0
  73. package/dist/documents.d.ts +20 -0
  74. package/dist/documents.d.ts.map +1 -0
  75. package/dist/documents.js +227 -0
  76. package/dist/documents.js.map +1 -0
  77. package/dist/embeddings.d.ts +15 -0
  78. package/dist/embeddings.d.ts.map +1 -0
  79. package/dist/embeddings.js +40 -0
  80. package/dist/embeddings.js.map +1 -0
  81. package/dist/factory.d.ts +72 -0
  82. package/dist/factory.d.ts.map +1 -0
  83. package/dist/factory.js +2010 -0
  84. package/dist/factory.js.map +1 -0
  85. package/dist/groups.d.ts +13 -0
  86. package/dist/groups.d.ts.map +1 -0
  87. package/dist/groups.js +42 -0
  88. package/dist/groups.js.map +1 -0
  89. package/dist/index.d.ts +2 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +223 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/lib/taskStorage.d.ts +4 -0
  94. package/dist/lib/taskStorage.d.ts.map +1 -0
  95. package/dist/lib/taskStorage.js +28 -0
  96. package/dist/lib/taskStorage.js.map +1 -0
  97. package/dist/llm/anthropic.d.ts +13 -0
  98. package/dist/llm/anthropic.d.ts.map +1 -0
  99. package/dist/llm/anthropic.js +96 -0
  100. package/dist/llm/anthropic.js.map +1 -0
  101. package/dist/llm/failover.d.ts +13 -0
  102. package/dist/llm/failover.d.ts.map +1 -0
  103. package/dist/llm/failover.js +42 -0
  104. package/dist/llm/failover.js.map +1 -0
  105. package/dist/llm/google.d.ts +13 -0
  106. package/dist/llm/google.d.ts.map +1 -0
  107. package/dist/llm/google.js +112 -0
  108. package/dist/llm/google.js.map +1 -0
  109. package/dist/llm/groq.d.ts +8 -0
  110. package/dist/llm/groq.d.ts.map +1 -0
  111. package/dist/llm/groq.js +13 -0
  112. package/dist/llm/groq.js.map +1 -0
  113. package/dist/llm/index.d.ts +11 -0
  114. package/dist/llm/index.d.ts.map +1 -0
  115. package/dist/llm/index.js +10 -0
  116. package/dist/llm/index.js.map +1 -0
  117. package/dist/llm/ollama.d.ts +9 -0
  118. package/dist/llm/ollama.d.ts.map +1 -0
  119. package/dist/llm/ollama.js +27 -0
  120. package/dist/llm/ollama.js.map +1 -0
  121. package/dist/llm/openai-compat.d.ts +17 -0
  122. package/dist/llm/openai-compat.d.ts.map +1 -0
  123. package/dist/llm/openai-compat.js +69 -0
  124. package/dist/llm/openai-compat.js.map +1 -0
  125. package/dist/llm/openrouter.d.ts +8 -0
  126. package/dist/llm/openrouter.d.ts.map +1 -0
  127. package/dist/llm/openrouter.js +20 -0
  128. package/dist/llm/openrouter.js.map +1 -0
  129. package/dist/llm/provider.d.ts +41 -0
  130. package/dist/llm/provider.d.ts.map +1 -0
  131. package/dist/llm/provider.js +2 -0
  132. package/dist/llm/provider.js.map +1 -0
  133. package/dist/llm/registry.d.ts +10 -0
  134. package/dist/llm/registry.d.ts.map +1 -0
  135. package/dist/llm/registry.js +90 -0
  136. package/dist/llm/registry.js.map +1 -0
  137. package/dist/llm/thinking.d.ts +7 -0
  138. package/dist/llm/thinking.d.ts.map +1 -0
  139. package/dist/llm/thinking.js +34 -0
  140. package/dist/llm/thinking.js.map +1 -0
  141. package/dist/llm.d.ts +17 -0
  142. package/dist/llm.d.ts.map +1 -0
  143. package/dist/llm.js +184 -0
  144. package/dist/llm.js.map +1 -0
  145. package/dist/logs.d.ts +11 -0
  146. package/dist/logs.d.ts.map +1 -0
  147. package/dist/logs.js +54 -0
  148. package/dist/logs.js.map +1 -0
  149. package/dist/memory/knowledge-graph.d.ts +34 -0
  150. package/dist/memory/knowledge-graph.d.ts.map +1 -0
  151. package/dist/memory/knowledge-graph.js +137 -0
  152. package/dist/memory/knowledge-graph.js.map +1 -0
  153. package/dist/memory.d.ts +73 -0
  154. package/dist/memory.d.ts.map +1 -0
  155. package/dist/memory.js +320 -0
  156. package/dist/memory.js.map +1 -0
  157. package/dist/mesh.d.ts +18 -0
  158. package/dist/mesh.d.ts.map +1 -0
  159. package/dist/mesh.js +120 -0
  160. package/dist/mesh.js.map +1 -0
  161. package/dist/paths.d.ts +11 -0
  162. package/dist/paths.d.ts.map +1 -0
  163. package/dist/paths.js +51 -0
  164. package/dist/paths.js.map +1 -0
  165. package/dist/proactive/heartbeat.d.ts +4 -0
  166. package/dist/proactive/heartbeat.d.ts.map +1 -0
  167. package/dist/proactive/heartbeat.js +56 -0
  168. package/dist/proactive/heartbeat.js.map +1 -0
  169. package/dist/proactive/recap.d.ts +12 -0
  170. package/dist/proactive/recap.d.ts.map +1 -0
  171. package/dist/proactive/recap.js +90 -0
  172. package/dist/proactive/recap.js.map +1 -0
  173. package/dist/proactive/recommendations.d.ts +11 -0
  174. package/dist/proactive/recommendations.d.ts.map +1 -0
  175. package/dist/proactive/recommendations.js +92 -0
  176. package/dist/proactive/recommendations.js.map +1 -0
  177. package/dist/projects.d.ts +44 -0
  178. package/dist/projects.d.ts.map +1 -0
  179. package/dist/projects.js +101 -0
  180. package/dist/projects.js.map +1 -0
  181. package/dist/scheduler/index.d.ts +17 -0
  182. package/dist/scheduler/index.d.ts.map +1 -0
  183. package/dist/scheduler/index.js +116 -0
  184. package/dist/scheduler/index.js.map +1 -0
  185. package/dist/sessions.d.ts +19 -0
  186. package/dist/sessions.d.ts.map +1 -0
  187. package/dist/sessions.js +176 -0
  188. package/dist/sessions.js.map +1 -0
  189. package/dist/skills/index.d.ts +14 -0
  190. package/dist/skills/index.d.ts.map +1 -0
  191. package/dist/skills/index.js +126 -0
  192. package/dist/skills/index.js.map +1 -0
  193. package/dist/swarm.d.ts +18 -0
  194. package/dist/swarm.d.ts.map +1 -0
  195. package/dist/swarm.js +146 -0
  196. package/dist/swarm.js.map +1 -0
  197. package/dist/taskListWidget.d.ts +76 -0
  198. package/dist/taskListWidget.d.ts.map +1 -0
  199. package/dist/taskListWidget.js +312 -0
  200. package/dist/taskListWidget.js.map +1 -0
  201. package/dist/tools/browser.d.ts +5 -0
  202. package/dist/tools/browser.d.ts.map +1 -0
  203. package/dist/tools/browser.js +104 -0
  204. package/dist/tools/browser.js.map +1 -0
  205. package/dist/tools/config-tools.d.ts +4 -0
  206. package/dist/tools/config-tools.d.ts.map +1 -0
  207. package/dist/tools/config-tools.js +154 -0
  208. package/dist/tools/config-tools.js.map +1 -0
  209. package/dist/tools/files.d.ts +3 -0
  210. package/dist/tools/files.d.ts.map +1 -0
  211. package/dist/tools/files.js +208 -0
  212. package/dist/tools/files.js.map +1 -0
  213. package/dist/tools/index.d.ts +11 -0
  214. package/dist/tools/index.d.ts.map +1 -0
  215. package/dist/tools/index.js +1109 -0
  216. package/dist/tools/index.js.map +1 -0
  217. package/dist/tools/mcp-bridge.d.ts +5 -0
  218. package/dist/tools/mcp-bridge.d.ts.map +1 -0
  219. package/dist/tools/mcp-bridge.js +200 -0
  220. package/dist/tools/mcp-bridge.js.map +1 -0
  221. package/dist/tools/shell.d.ts +8 -0
  222. package/dist/tools/shell.d.ts.map +1 -0
  223. package/dist/tools/shell.js +78 -0
  224. package/dist/tools/shell.js.map +1 -0
  225. package/dist/tools/skills-manage.d.ts +25 -0
  226. package/dist/tools/skills-manage.d.ts.map +1 -0
  227. package/dist/tools/skills-manage.js +155 -0
  228. package/dist/tools/skills-manage.js.map +1 -0
  229. package/dist/tools/web-search.d.ts +4 -0
  230. package/dist/tools/web-search.d.ts.map +1 -0
  231. package/dist/tools/web-search.js +60 -0
  232. package/dist/tools/web-search.js.map +1 -0
  233. package/dist/tts.d.ts +6 -0
  234. package/dist/tts.d.ts.map +1 -0
  235. package/dist/tts.js +42 -0
  236. package/dist/tts.js.map +1 -0
  237. package/dist/types/task.d.ts +7 -0
  238. package/dist/types/task.d.ts.map +1 -0
  239. package/dist/types/task.js +2 -0
  240. package/dist/types/task.js.map +1 -0
  241. package/dist/typing.d.ts +18 -0
  242. package/dist/typing.d.ts.map +1 -0
  243. package/dist/typing.js +63 -0
  244. package/dist/typing.js.map +1 -0
  245. package/dist/usage.d.ts +28 -0
  246. package/dist/usage.d.ts.map +1 -0
  247. package/dist/usage.js +69 -0
  248. package/dist/usage.js.map +1 -0
  249. package/dist/voice.d.ts +6 -0
  250. package/dist/voice.d.ts.map +1 -0
  251. package/dist/voice.js +47 -0
  252. package/dist/voice.js.map +1 -0
  253. package/dist/webchat/index.d.ts +3 -0
  254. package/dist/webchat/index.d.ts.map +1 -0
  255. package/dist/webchat/index.js +3 -0
  256. package/dist/webchat/index.js.map +1 -0
  257. package/dist/webchat/public/index.html +344 -0
  258. package/dist/webchat/public/public/index.html +344 -0
  259. package/dist/webchat/public/public/task-list-widget.js +410 -0
  260. package/dist/webchat/public/task-list-widget.js +410 -0
  261. package/dist/webchat/server.d.ts +3 -0
  262. package/dist/webchat/server.d.ts.map +1 -0
  263. package/dist/webchat/server.js +80 -0
  264. package/dist/webchat/server.js.map +1 -0
  265. package/dist/webchat/ws.d.ts +4 -0
  266. package/dist/webchat/ws.d.ts.map +1 -0
  267. package/dist/webchat/ws.js +232 -0
  268. package/dist/webchat/ws.js.map +1 -0
  269. package/dist/webhooks/index.d.ts +14 -0
  270. package/dist/webhooks/index.d.ts.map +1 -0
  271. package/dist/webhooks/index.js +86 -0
  272. package/dist/webhooks/index.js.map +1 -0
  273. package/package.json +53 -0
@@ -0,0 +1,410 @@
1
+ /**
2
+ * Task List Widget — US-3 Implementation
3
+ *
4
+ * Core Requirements:
5
+ * 1. Checkbox on every task item
6
+ * 2. Click toggles the task's `completed` boolean in state
7
+ * 3. Conditionally apply a visual indicator class to the DOM element
8
+ *
9
+ * Defensive fixes applied (from review iterations):
10
+ * 4. Null-safe checkbox access in programmatic toggle
11
+ * 5. Duplicate mount prevention (idempotent mount)
12
+ * 6. setTasks() filters null/invalid entries
13
+ * 7. Re-entrancy guard on toggleCompleted to prevent rapid double-toggle
14
+ * 8. CSS.escape() for querySelector to prevent injection
15
+ * 9. No stacked opacity — only color + line-through on completed items
16
+ */
17
+ (function (root) {
18
+ "use strict";
19
+
20
+ // ─── Unique ID generator ───────────────────────────────────────────────────
21
+ var _counter = 0;
22
+ function uid() {
23
+ return "task-" + Date.now().toString(36) + "-" + (++_counter);
24
+ }
25
+
26
+ // ─── CSS selector escaping ─────────────────────────────────────────────────
27
+ // Prevents DOM injection when task IDs from external data contain special
28
+ // characters (`, `"`, `]`, etc.) that would break attribute selectors.
29
+ function escapeSelector(str) {
30
+ if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
31
+ return CSS.escape(str);
32
+ }
33
+ // Manual fallback for environments without CSS.escape()
34
+ return String(str)
35
+ .replace(/\\/g, "\\\\")
36
+ .replace(/"/g, '\\"')
37
+ .replace(/'/g, "\\'")
38
+ .replace(/\[/g, "\\[")
39
+ .replace(/\]/g, "\\]");
40
+ }
41
+
42
+ // ─── Default styles (injected once) ────────────────────────────────────────
43
+ var STYLES =
44
+ ".task-list-widget{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif}" +
45
+ ".task-list-widget__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}" +
46
+ ".task-list-widget__title{font-size:16px;font-weight:600}" +
47
+ ".task-list-widget__count{font-size:13px;color:#8b949e}" +
48
+ ".task-list-widget__input-row{display:flex;gap:8px;margin-bottom:16px}" +
49
+ ".task-list-widget__input{flex:1;padding:8px 12px;border:1px solid #30363d;border-radius:8px;background:#0d1117;color:#e6edf3;font-size:14px;outline:none}" +
50
+ ".task-list-widget__input:focus{border-color:#58a6ff}" +
51
+ ".task-list-widget__add-btn{padding:8px 16px;background:#1f6feb;color:#fff;border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer}" +
52
+ ".task-list-widget__add-btn:hover{background:#58a6ff}" +
53
+ ".task-list-widget__items{list-style:none;display:flex;flex-direction:column;gap:6px}" +
54
+ ".task-item{display:flex;align-items:center;gap:10px;padding:8px 12px;border-radius:8px;background:#161b22;border:1px solid #30363d;transition:background .15s}" +
55
+ ".task-item:hover{background:#1c2129}" +
56
+ // ── REQUIREMENT 3: Visual indicator class ──
57
+ // Uses only `color` + `text-decoration` (no stacked opacity).
58
+ ".task-item--completed .task-item__text{color:#8b949e;text-decoration:line-through}" +
59
+ ".task-item__checkbox{width:18px;height:18px;accent-color:#58a6ff;cursor:pointer;flex-shrink:0}" +
60
+ ".task-item__text{flex:1;font-size:14px;color:#e6edf3;word-break:break-word;transition:color .15s,text-decoration .15s}" +
61
+ ".task-item__remove{background:none;border:none;color:#8b949e;cursor:pointer;font-size:18px;padding:0 4px;line-height:1}" +
62
+ ".task-item__remove:hover{color:#f85149}" +
63
+ ".task-list-widget__empty{text-align:center;color:#8b949e;font-size:13px;padding:24px 0}";
64
+
65
+ var styleInjected = false;
66
+
67
+ function injectStyles() {
68
+ if (styleInjected) return;
69
+ var el = document.createElement("style");
70
+ el.textContent = STYLES;
71
+ document.head.appendChild(el);
72
+ styleInjected = true;
73
+ }
74
+
75
+ // ─── Widget Factory ────────────────────────────────────────────────────────
76
+ function createTaskListWidget(containerEl) {
77
+ injectStyles();
78
+
79
+ // State
80
+ var tasks = [];
81
+ var mounted = false;
82
+
83
+ // ── FIX 7: Re-entrancy guard ──
84
+ // Tracks IDs currently being toggled so rapid-fire events don't
85
+ // flip the state back and forth.
86
+ var togglingIds = Object.create(null);
87
+
88
+ // DOM references (set in mount)
89
+ var rootEl, itemsEl, countEl, inputEl;
90
+
91
+ // ────────────────────────────────────────────────────────────────────────
92
+ // Public API
93
+ // ────────────────────────────────────────────────────────────────────────
94
+
95
+ /**
96
+ * Add a new task to state and re-render.
97
+ */
98
+ function addTask(text, completed) {
99
+ if (text === undefined || text === null) text = "";
100
+ tasks.push({
101
+ id: uid(),
102
+ text: String(text),
103
+ completed: !!completed,
104
+ });
105
+ if (mounted) renderList();
106
+ }
107
+
108
+ /**
109
+ * Replace entire task list. Filters out null/undefined/invalid entries.
110
+ */
111
+ function setTasks(arr) {
112
+ tasks = [];
113
+ if (!Array.isArray(arr)) return;
114
+ for (var i = 0; i < arr.length; i++) {
115
+ // ── FIX 6: Filter null / invalid entries ──
116
+ var t = arr[i];
117
+ if (!t || typeof t !== "object") continue;
118
+ tasks.push({
119
+ id: t.id || uid(),
120
+ text: t.text !== undefined ? String(t.text) : "",
121
+ completed: !!t.completed,
122
+ });
123
+ }
124
+ if (mounted) renderList();
125
+ }
126
+
127
+ /**
128
+ * Toggle the `completed` boolean for a task by ID.
129
+ * Works both when triggered by user (checkbox change) and programmatically
130
+ * via the public API.
131
+ *
132
+ * ── FIX 7: Re-entrancy guard ──
133
+ * If the ID is already mid-toggle, this is a no-op.
134
+ *
135
+ * ── FIX 8: Selector injection prevention ──
136
+ * Uses escapeSelector() on the ID before building the querySelector.
137
+ *
138
+ * ── FIX 4: Null-safe checkbox access ──
139
+ * Both `.checked` and `.setAttribute()` are guarded by a single
140
+ * `if (checkbox)` block so a missing checkbox never throws.
141
+ */
142
+ function toggleCompleted(taskId) {
143
+ // Re-entrancy guard
144
+ if (togglingIds[taskId]) return;
145
+ togglingIds[taskId] = true;
146
+ try {
147
+ var task = null;
148
+ for (var i = 0; i < tasks.length; i++) {
149
+ if (tasks[i].id === taskId) { task = tasks[i]; break; }
150
+ }
151
+ if (!task) return;
152
+
153
+ task.completed = !task.completed;
154
+
155
+ if (mounted && itemsEl) {
156
+ var selector = '.task-item[data-task-id="' + escapeSelector(taskId) + '"]';
157
+ var itemEl = itemsEl.querySelector(selector);
158
+ if (itemEl) {
159
+ // Apply / remove visual indicator class (REQUIREMENT 3)
160
+ if (task.completed) {
161
+ itemEl.classList.add("task-item--completed");
162
+ } else {
163
+ itemEl.classList.remove("task-item--completed");
164
+ }
165
+
166
+ // FIX 4: Null-safe checkbox — both accesses inside one guard
167
+ var checkbox = itemEl.querySelector('input[type="checkbox"]');
168
+ if (checkbox) {
169
+ checkbox.checked = task.completed;
170
+ checkbox.setAttribute(
171
+ "aria-label",
172
+ 'Mark "' + task.text + '" as ' + (task.completed ? "incomplete" : "complete")
173
+ );
174
+ }
175
+ }
176
+ }
177
+
178
+ updateCount();
179
+ } finally {
180
+ // Always clean up the re-entrancy flag
181
+ delete togglingIds[taskId];
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Remove a task by ID. Uses escapeSelector for safety.
187
+ */
188
+ function removeTask(taskId) {
189
+ tasks = tasks.filter(function (t) { return t.id !== taskId; });
190
+ if (mounted) renderList();
191
+ }
192
+
193
+ /**
194
+ * Return a shallow copy of the current task array.
195
+ */
196
+ function getTasks() {
197
+ return tasks.slice();
198
+ }
199
+
200
+ // ────────────────────────────────────────────────────────────────────────
201
+ // Internal helpers
202
+ // ────────────────────────────────────────────────────────────────────────
203
+
204
+ function updateCount() {
205
+ if (!countEl) return;
206
+ var total = tasks.length;
207
+ var done = 0;
208
+ for (var i = 0; i < tasks.length; i++) {
209
+ if (tasks[i].completed) done++;
210
+ }
211
+ countEl.textContent = done + " / " + total + " completed";
212
+ }
213
+
214
+ /**
215
+ * Build the full list DOM from current state.
216
+ */
217
+ function renderList() {
218
+ if (!itemsEl) return;
219
+ itemsEl.innerHTML = "";
220
+
221
+ if (tasks.length === 0) {
222
+ var empty = document.createElement("li");
223
+ empty.className = "task-list-widget__empty";
224
+ empty.textContent = "No tasks yet. Add one above.";
225
+ itemsEl.appendChild(empty);
226
+ updateCount();
227
+ return;
228
+ }
229
+
230
+ for (var i = 0; i < tasks.length; i++) {
231
+ var task = tasks[i];
232
+ itemsEl.appendChild(buildTaskElement(task));
233
+ }
234
+
235
+ updateCount();
236
+ }
237
+
238
+ /**
239
+ * Create a single <li> element for a task.
240
+ *
241
+ * ── REQUIREMENT 1: Checkbox on every task item ──
242
+ * An <input type="checkbox"> is the first child, wrapped inside a <label>
243
+ * so clicking the text also toggles the checkbox.
244
+ *
245
+ * ── REQUIREMENT 2: Click toggles `completed` boolean ──
246
+ * The checkbox `change` event calls toggleCompleted(taskId).
247
+ *
248
+ * ── REQUIREMENT 3: Visual indicator class ──
249
+ * If task.completed is true, the li gets class `task-item--completed`
250
+ * which applies line-through + muted color via CSS.
251
+ */
252
+ function buildTaskElement(task) {
253
+ var li = document.createElement("li");
254
+ li.className = "task-item";
255
+ if (task.completed) {
256
+ li.classList.add("task-item--completed");
257
+ }
258
+ li.setAttribute("data-task-id", task.id);
259
+
260
+ // REQUIREMENT 1: Checkbox input on every task item
261
+ var label = document.createElement("label");
262
+ label.style.cssText = "display:flex;align-items:center;gap:10px;flex:1;cursor:pointer;min-width:0;";
263
+
264
+ var checkbox = document.createElement("input");
265
+ checkbox.type = "checkbox";
266
+ checkbox.className = "task-item__checkbox";
267
+ checkbox.checked = !!task.completed;
268
+ checkbox.setAttribute(
269
+ "aria-label",
270
+ 'Mark "' + task.text + '" as ' + (task.completed ? "incomplete" : "complete")
271
+ );
272
+
273
+ // REQUIREMENT 2: change event toggles completed boolean
274
+ checkbox.addEventListener("change", function () {
275
+ toggleCompleted(task.id);
276
+ });
277
+
278
+ var textSpan = document.createElement("span");
279
+ textSpan.className = "task-item__text";
280
+ textSpan.textContent = task.text;
281
+
282
+ label.appendChild(checkbox);
283
+ label.appendChild(textSpan);
284
+
285
+ var removeBtn = document.createElement("button");
286
+ removeBtn.className = "task-item__remove";
287
+ removeBtn.textContent = "×";
288
+ removeBtn.title = "Remove task";
289
+ removeBtn.addEventListener("click", function () {
290
+ removeTask(task.id);
291
+ });
292
+
293
+ li.appendChild(label);
294
+ li.appendChild(removeBtn);
295
+
296
+ return li;
297
+ }
298
+
299
+ // ────────────────────────────────────────────────────────────────────────
300
+ // Mount / Unmount
301
+ // ────────────────────────────────────────────────────────────────────────
302
+
303
+ /**
304
+ * Mount the widget into the given container.
305
+ *
306
+ * ── FIX 5: Duplicate mount prevention ──
307
+ * If already mounted, unmounts first to prevent orphaned DOM nodes
308
+ * and duplicate event listeners.
309
+ */
310
+ function mount() {
311
+ if (mounted) unmount();
312
+
313
+ rootEl = document.createElement("div");
314
+ rootEl.className = "task-list-widget";
315
+
316
+ var header = document.createElement("div");
317
+ header.className = "task-list-widget__header";
318
+
319
+ var title = document.createElement("div");
320
+ title.className = "task-list-widget__title";
321
+ title.textContent = "Tasks";
322
+
323
+ countEl = document.createElement("div");
324
+ countEl.className = "task-list-widget__count";
325
+ countEl.textContent = "0 / 0 completed";
326
+
327
+ header.appendChild(title);
328
+ header.appendChild(countEl);
329
+
330
+ var inputRow = document.createElement("div");
331
+ inputRow.className = "task-list-widget__input-row";
332
+
333
+ inputEl = document.createElement("input");
334
+ inputEl.className = "task-list-widget__input";
335
+ inputEl.type = "text";
336
+ inputEl.placeholder = "Add a new task…";
337
+
338
+ var addBtn = document.createElement("button");
339
+ addBtn.className = "task-list-widget__add-btn";
340
+ addBtn.textContent = "Add";
341
+
342
+ addBtn.addEventListener("click", function () {
343
+ var text = inputEl.value.trim();
344
+ if (text) {
345
+ addTask(text);
346
+ inputEl.value = "";
347
+ inputEl.focus();
348
+ }
349
+ });
350
+
351
+ inputEl.addEventListener("keydown", function (e) {
352
+ if (e.key === "Enter") {
353
+ addBtn.click();
354
+ }
355
+ });
356
+
357
+ inputRow.appendChild(inputEl);
358
+ inputRow.appendChild(addBtn);
359
+
360
+ itemsEl = document.createElement("ul");
361
+ itemsEl.className = "task-list-widget__items";
362
+
363
+ rootEl.appendChild(header);
364
+ rootEl.appendChild(inputRow);
365
+ rootEl.appendChild(itemsEl);
366
+
367
+ containerEl.innerHTML = "";
368
+ containerEl.appendChild(rootEl);
369
+
370
+ mounted = true;
371
+ renderList();
372
+ }
373
+
374
+ function unmount() {
375
+ if (rootEl && rootEl.parentNode) {
376
+ rootEl.parentNode.removeChild(rootEl);
377
+ }
378
+ rootEl = null;
379
+ itemsEl = null;
380
+ countEl = null;
381
+ inputEl = null;
382
+ mounted = false;
383
+ }
384
+
385
+ // ────────────────────────────────────────────────────────────────────────
386
+ // Return public surface
387
+ // ────────────────────────────────────────────────────────────────────────
388
+
389
+ var widget = {
390
+ mount: mount,
391
+ unmount: unmount,
392
+ addTask: addTask,
393
+ setTasks: setTasks,
394
+ toggleCompleted: toggleCompleted,
395
+ removeTask: removeTask,
396
+ getTasks: getTasks,
397
+ };
398
+
399
+ // Expose globally for debugging / programmatic access
400
+ root.__taskListWidget = widget;
401
+
402
+ return widget;
403
+ }
404
+
405
+ // Export for CommonJS / ESM interop
406
+ if (typeof module !== "undefined" && module.exports) {
407
+ module.exports = createTaskListWidget;
408
+ }
409
+ root.createTaskListWidget = createTaskListWidget;
410
+ })(typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : this);
@@ -0,0 +1,3 @@
1
+ import http from "node:http";
2
+ export declare function startWebchatServer(port: number, authToken?: string): Promise<http.Server>;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/webchat/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAuE7B,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAatB"}
@@ -0,0 +1,80 @@
1
+ import http from "node:http";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { createWSServer } from "./ws.js";
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ const BUILTIN_PUBLIC_DIR = path.join(__dirname, "public");
8
+ const DASHBOARD_DIR = path.join(__dirname, "..", "dashboard");
9
+ function getDashboardDir() {
10
+ if (fs.existsSync(DASHBOARD_DIR) && fs.readdirSync(DASHBOARD_DIR).length > 0) {
11
+ return DASHBOARD_DIR;
12
+ }
13
+ return null;
14
+ }
15
+ const MIME_TYPES = {
16
+ ".html": "text/html",
17
+ ".css": "text/css",
18
+ ".js": "application/javascript",
19
+ ".json": "application/json",
20
+ ".png": "image/png",
21
+ ".jpg": "image/jpeg",
22
+ ".svg": "image/svg+xml",
23
+ ".ico": "image/x-icon",
24
+ ".woff": "font/woff",
25
+ ".woff2": "font/woff2",
26
+ ".ttf": "font/ttf",
27
+ ".map": "application/json",
28
+ };
29
+ function serveStatic(req, res) {
30
+ const urlPath = req.url?.split("?")[0] || "/";
31
+ const dashboardDir = getDashboardDir();
32
+ const publicDir = dashboardDir || BUILTIN_PUBLIC_DIR;
33
+ let filePath;
34
+ if (urlPath === "/" || urlPath === "/index.html") {
35
+ filePath = path.join(publicDir, "index.html");
36
+ }
37
+ else {
38
+ const sanitized = urlPath.replace(/\.\./g, "").replace(/^\//, "");
39
+ filePath = path.join(publicDir, sanitized);
40
+ }
41
+ if (!fs.existsSync(filePath)) {
42
+ if (fs.existsSync(filePath + "/index.html")) {
43
+ filePath = filePath + "/index.html";
44
+ }
45
+ else if (dashboardDir && fs.existsSync(path.join(dashboardDir, "404.html"))) {
46
+ filePath = path.join(dashboardDir, "404.html");
47
+ }
48
+ else {
49
+ res.writeHead(404, { "Content-Type": "text/plain" });
50
+ res.end("Not Found");
51
+ return;
52
+ }
53
+ }
54
+ const ext = path.extname(filePath);
55
+ const contentType = MIME_TYPES[ext] || "application/octet-stream";
56
+ try {
57
+ const content = fs.readFileSync(filePath);
58
+ res.writeHead(200, { "Content-Type": contentType });
59
+ res.end(content);
60
+ }
61
+ catch {
62
+ res.writeHead(500, { "Content-Type": "text/plain" });
63
+ res.end("Internal Server Error");
64
+ }
65
+ }
66
+ export function startWebchatServer(port, authToken) {
67
+ return new Promise((resolve) => {
68
+ const server = http.createServer((req, res) => {
69
+ const urlPath = req.url?.split("?")[0] || "/";
70
+ if (urlPath.startsWith("/api/") || urlPath.startsWith("/webhook/"))
71
+ return;
72
+ serveStatic(req, res);
73
+ });
74
+ createWSServer(server, authToken);
75
+ server.listen(port, () => {
76
+ resolve(server);
77
+ });
78
+ });
79
+ }
80
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/webchat/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { WebSocketServer } from "ws";
2
+ import type { Server } from "node:http";
3
+ export declare function createWSServer(httpServer: Server, authToken?: string): WebSocketServer;
4
+ //# sourceMappingURL=ws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/webchat/ws.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAoDxC,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,eAAe,CAqFjB"}