openclacky 1.2.5 → 1.2.6

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.
@@ -492,57 +492,12 @@ const Sessions = (() => {
492
492
  const MAX_IMAGE_LONG_EDGE = 1920; // px — scale down if larger
493
493
  const MAX_FILE_BYTES = 32 * 1024 * 1024; // 32 MB
494
494
  const ACCEPTED_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
495
- const ACCEPTED_DOC_TYPES = [
496
- "application/pdf",
497
- "application/zip",
498
- "application/x-zip-compressed",
499
- "application/gzip",
500
- "application/x-gzip",
501
- "application/x-tar",
502
- "application/x-compressed-tar",
503
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .docx
504
- "application/msword", // .doc
505
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xlsx
506
- "application/vnd.ms-excel", // .xls
507
- "application/vnd.openxmlformats-officedocument.presentationml.presentation", // .pptx
508
- "application/vnd.ms-powerpoint", // .ppt
509
- "text/csv", // .csv
510
- "application/csv", // .csv (some browsers)
511
- "text/markdown", // .md
512
- "text/x-markdown", // .md (some browsers)
513
- "text/plain", // .md / .txt (many browsers report this)
514
- ];
515
-
516
- // Extension-based fallback for files whose MIME type is missing or unreliable.
517
- // Browsers frequently report "" or "application/octet-stream" for .md / .tar.gz.
518
- const ACCEPTED_DOC_EXTENSIONS = [
519
- ".pdf", ".zip",
520
- ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx",
521
- ".csv",
522
- ".md", ".markdown", ".txt", ".log",
523
- ".tar", ".gz", ".tgz", ".tar.gz", ".rar", ".7z"
524
- ];
525
-
526
- function _hasAcceptedDocExt(filename) {
527
- const lower = (filename || "").toLowerCase();
528
- return ACCEPTED_DOC_EXTENSIONS.some(ext => lower.endsWith(ext));
529
- }
530
-
531
- function _isAcceptedDoc(file) {
532
- if (!file) return false;
533
- if (file.type && ACCEPTED_DOC_TYPES.includes(file.type)) return true;
534
- return _hasAcceptedDocExt(file.name);
535
- }
536
495
 
537
496
  function _isAcceptedImage(file) {
538
497
  if (!file) return false;
539
498
  return ACCEPTED_IMAGE_TYPES.includes(file.type);
540
499
  }
541
500
 
542
- function _isAcceptedFile(file) {
543
- return _isAcceptedImage(file) || _isAcceptedDoc(file);
544
- }
545
-
546
501
  function _docTypeIcon(mimeType, filename) {
547
502
  const lower = (filename || "").toLowerCase();
548
503
  if (mimeType === "application/pdf" || lower.endsWith(".pdf")) return "📄";
@@ -552,11 +507,11 @@ const Sessions = (() => {
552
507
  lower.endsWith(".tar") || lower.endsWith(".gz") || lower.endsWith(".tgz") || lower.endsWith(".tar.gz") ||
553
508
  lower.endsWith(".rar") || lower.endsWith(".7z")) return "🗜️";
554
509
  if ((mimeType && mimeType.includes("wordprocessingml")) || mimeType === "application/msword" ||
555
- lower.endsWith(".doc") || lower.endsWith(".docx")) return "📝";
510
+ lower.endsWith(".doc") || lower.endsWith(".docx") || lower.endsWith(".wps")) return "📝";
556
511
  if ((mimeType && mimeType.includes("spreadsheetml")) || mimeType === "application/vnd.ms-excel" ||
557
- lower.endsWith(".xls") || lower.endsWith(".xlsx")) return "📊";
512
+ lower.endsWith(".xls") || lower.endsWith(".xlsx") || lower.endsWith(".et")) return "📊";
558
513
  if ((mimeType && mimeType.includes("presentationml")) || mimeType === "application/vnd.ms-powerpoint" ||
559
- lower.endsWith(".ppt") || lower.endsWith(".pptx")) return "📋";
514
+ lower.endsWith(".ppt") || lower.endsWith(".pptx") || lower.endsWith(".dps")) return "📋";
560
515
  if (mimeType === "text/csv" || mimeType === "application/csv" || lower.endsWith(".csv")) return "📊";
561
516
  if (mimeType === "text/markdown" || mimeType === "text/x-markdown" ||
562
517
  lower.endsWith(".md") || lower.endsWith(".markdown")) return "📝";
@@ -649,16 +604,10 @@ const Sessions = (() => {
649
604
  }
650
605
 
651
606
  function _addAttachmentFile(file) {
652
- // Route by content category. Images must match known image MIME types
653
- // (MIME is reliable for images). Documents fall back to extension-based
654
- // detection because browsers frequently report "" or "application/octet-stream"
655
- // for .md / .tar.gz files.
656
607
  if (_isAcceptedImage(file)) {
657
608
  _addImageFile(file);
658
- } else if (_isAcceptedDoc(file)) {
659
- _addGenericFile(file);
660
609
  } else {
661
- alert(`Unsupported file: ${file.name}\nSupported: images (PNG/JPG/GIF/WEBP), PDF, Office (DOC/XLS/PPT), ZIP, TAR, TAR.GZ, MD, TXT, CSV`);
610
+ _addGenericFile(file);
662
611
  }
663
612
  }
664
613
 
@@ -848,27 +797,20 @@ const Sessions = (() => {
848
797
  inputArea.addEventListener("drop", (e) => {
849
798
  e.preventDefault();
850
799
  inputArea.classList.remove("drag-over");
851
- const files = Array.from(e.dataTransfer.files).filter(_isAcceptedFile);
800
+ const files = Array.from(e.dataTransfer.files);
852
801
  if (files.length === 0) return;
853
802
  files.forEach(_addAttachmentFile);
854
803
  });
855
804
 
856
- // Paste handler — images and accepted docs from the clipboard.
857
805
  document.getElementById("user-input").addEventListener("paste", (e) => {
858
806
  const items = Array.from(e.clipboardData?.items || []);
859
- // Any file-kind item that's an image, or a document whose type/name
860
- // passes our doc filter. Must check name via getAsFile() for .md/.tar.gz
861
- // (browsers often leave item.type empty for these).
862
- const attachItems = items.filter(it => {
863
- if (it.kind !== "file") return false;
864
- if (ACCEPTED_IMAGE_TYPES.includes(it.type)) return true;
865
- if (ACCEPTED_DOC_TYPES.includes(it.type)) return true;
866
- const f = it.getAsFile && it.getAsFile();
867
- return f ? _hasAcceptedDocExt(f.name) : false;
868
- });
807
+ const attachItems = items.filter(it => it.kind === "file");
869
808
  if (attachItems.length === 0) return;
870
809
  e.preventDefault();
871
- attachItems.forEach(it => _addAttachmentFile(it.getAsFile()));
810
+ attachItems.forEach(it => {
811
+ const f = it.getAsFile && it.getAsFile();
812
+ if (f) _addAttachmentFile(f);
813
+ });
872
814
  });
873
815
  }
874
816
 
data/lib/clacky.rb CHANGED
@@ -118,9 +118,6 @@ require_relative "clacky/tools/todo_manager"
118
118
  require_relative "clacky/tools/trash_manager"
119
119
  require_relative "clacky/tools/request_user_feedback"
120
120
  require_relative "clacky/tools/invoke_skill"
121
- require_relative "clacky/tools/undo_task"
122
- require_relative "clacky/tools/redo_task"
123
- require_relative "clacky/tools/list_tasks"
124
121
  require_relative "clacky/tools/browser"
125
122
  require_relative "clacky/tools/terminal"
126
123
  require_relative "clacky/mcp/client"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openclacky
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-27 00:00:00.000000000 Z
11
+ date: 2026-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -360,6 +360,7 @@ files:
360
360
  - lib/clacky/default_parsers/pdf_parser_ocr.py
361
361
  - lib/clacky/default_parsers/pdf_parser_plumber.py
362
362
  - lib/clacky/default_parsers/pptx_parser.rb
363
+ - lib/clacky/default_parsers/wps_parser.rb
363
364
  - lib/clacky/default_parsers/xlsx_parser.rb
364
365
  - lib/clacky/default_skills/browser-setup/SKILL.md
365
366
  - lib/clacky/default_skills/channel-manager/SKILL.md
@@ -461,8 +462,6 @@ files:
461
462
  - lib/clacky/tools/glob.rb
462
463
  - lib/clacky/tools/grep.rb
463
464
  - lib/clacky/tools/invoke_skill.rb
464
- - lib/clacky/tools/list_tasks.rb
465
- - lib/clacky/tools/redo_task.rb
466
465
  - lib/clacky/tools/request_user_feedback.rb
467
466
  - lib/clacky/tools/security.rb
468
467
  - lib/clacky/tools/terminal.rb
@@ -472,7 +471,6 @@ files:
472
471
  - lib/clacky/tools/terminal/session_manager.rb
473
472
  - lib/clacky/tools/todo_manager.rb
474
473
  - lib/clacky/tools/trash_manager.rb
475
- - lib/clacky/tools/undo_task.rb
476
474
  - lib/clacky/tools/web_fetch.rb
477
475
  - lib/clacky/tools/web_search.rb
478
476
  - lib/clacky/tools/write.rb
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Clacky
4
- module Tools
5
- # Tool for listing task history (Time Machine feature)
6
- class ListTasks < Base
7
- self.tool_name = "list_tasks"
8
- self.tool_description = "List recent tasks in the task history with summaries. " \
9
- "Shows current task, past tasks, and future tasks (after undo). " \
10
- "Use when user wants to see task history or choose which task to undo/redo to."
11
- self.tool_category = "time_machine"
12
- self.tool_parameters = {
13
- type: "object",
14
- properties: {
15
- limit: {
16
- type: "integer",
17
- description: "Maximum number of recent tasks to show (default: 10)",
18
- default: 10
19
- }
20
- }
21
- }
22
-
23
- def execute(agent:, limit: 10, **_args)
24
- history = agent.get_task_history(limit: limit)
25
-
26
- if history.empty?
27
- return "No task history available."
28
- end
29
-
30
- lines = ["Task History:"]
31
- history.each do |task|
32
- indicator = case task[:status]
33
- when :current then "→"
34
- when :past then " "
35
- when :future then "↯"
36
- end
37
-
38
- branch_indicator = task[:has_branches] ? " ⎇" : ""
39
- lines << "#{indicator}#{branch_indicator} Task #{task[:task_id]}: #{task[:summary]}"
40
- end
41
-
42
- lines.join("\n")
43
- end
44
-
45
- def format_call(limit: 10, **_args)
46
- "Listing task history (limit: #{limit})..."
47
- end
48
-
49
- def format_result(result)
50
- result
51
- end
52
- end
53
- end
54
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Clacky
4
- module Tools
5
- # Tool for redoing a task after undo (Time Machine feature)
6
- class RedoTask < Base
7
- self.tool_name = "redo_task"
8
- self.tool_description = "Redo to a specific task after undo. Restores files to that task's state. " \
9
- "Use when user wants to go forward to a future task or switch to a different branch."
10
- self.tool_category = "time_machine"
11
- self.tool_parameters = {
12
- type: "object",
13
- properties: {
14
- task_id: {
15
- type: "integer",
16
- description: "The task ID to redo to (must be greater than current active task)"
17
- }
18
- },
19
- required: ["task_id"]
20
- }
21
-
22
- def execute(agent:, task_id:, **_args)
23
- result = agent.switch_to_task(task_id)
24
-
25
- if result[:success]
26
- result[:message]
27
- else
28
- "Error: #{result[:message]}"
29
- end
30
- end
31
-
32
- def format_call(task_id:, **_args)
33
- "Redoing to task #{task_id}..."
34
- end
35
-
36
- def format_result(result)
37
- result
38
- end
39
- end
40
- end
41
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Clacky
4
- module Tools
5
- # Tool for undoing the last task (Time Machine feature)
6
- class UndoTask < Base
7
- self.tool_name = "undo_task"
8
- self.tool_description = "Undo the last task and restore files to previous state. " \
9
- "Use when user wants to go back to previous state or undo recent changes."
10
- self.tool_category = "time_machine"
11
- self.tool_parameters = {
12
- type: "object",
13
- properties: {}
14
- }
15
-
16
- def execute(agent:, **_args)
17
- result = agent.undo_last_task
18
-
19
- if result[:success]
20
- result[:message]
21
- else
22
- "Error: #{result[:message]}"
23
- end
24
- end
25
-
26
- def format_call(**_args)
27
- "Undoing last task..."
28
- end
29
-
30
- def format_result(result)
31
- result
32
- end
33
- end
34
- end
35
- end