anki_generator 1.1.0 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +59 -0
- data/.rubocop.yml +79 -0
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +173 -0
- data/Gemfile +21 -0
- data/Makefile +20 -0
- data/README.md +160 -32
- data/Rakefile +174 -0
- data/anki_generator.gemspec +42 -0
- data/bin/anki_generator +3 -2
- data/docs/CI_SETUP.md +120 -0
- data/docs/architecture/current-v1.3.0.architecture.json +315 -0
- data/docs/architecture/current-v1.3.0.html +14990 -0
- data/docs/architecture/current-v1.3.0.visual-check.json +548 -0
- data/docs/architecture/phase3-proposed.architecture.json +310 -0
- data/docs/architecture/phase3-proposed.html +15001 -0
- data/docs/architecture/phase3-proposed.visual-check.json +548 -0
- data/docs/phase3-draft.md +86 -0
- data/examples/example_class.rb +13 -0
- data/examples/manual_cards.yaml +5 -0
- data/examples/study_prompt.txt +3 -0
- data/input/input.yaml.example +3 -0
- data/lib/anki_generator/anki_connect_client.rb +85 -0
- data/lib/anki_generator/apkg_schema.rb +257 -0
- data/lib/anki_generator/apkg_writer.rb +149 -0
- data/lib/anki_generator/card.rb +83 -0
- data/lib/anki_generator/cli.rb +183 -0
- data/lib/anki_generator/client_factory.rb +20 -0
- data/lib/anki_generator/commands/create_ai_template.rb +39 -0
- data/lib/anki_generator/commands/generate_deck.rb +43 -0
- data/lib/anki_generator/commands/generate_yaml.rb +63 -0
- data/lib/anki_generator/commands/import.rb +75 -0
- data/lib/anki_generator/commands/prompt_based.rb +74 -0
- data/lib/anki_generator/commands/prompt_to_deck.rb +84 -0
- data/lib/anki_generator/commands/push.rb +32 -0
- data/lib/anki_generator/commands/serve.rb +99 -0
- data/lib/anki_generator/commands/test_api.rb +33 -0
- data/lib/anki_generator/deck_builder.rb +184 -0
- data/lib/anki_generator/errors.rb +22 -0
- data/lib/anki_generator/file_processor.rb +154 -0
- data/lib/anki_generator/importers/csv.rb +52 -0
- data/lib/anki_generator/importers/markdown.rb +72 -0
- data/lib/anki_generator/prompt_builder.rb +77 -0
- data/lib/anki_generator/server.rb +98 -0
- data/lib/anki_generator/ui.rb +28 -0
- data/lib/anki_generator/version.rb +5 -0
- data/lib/anki_generator.rb +18 -114
- data/prompt.txt +5 -0
- metadata +100 -43
- data/lib/anki_cli.rb +0 -259
- data/lib/file_processor.rb +0 -156
- data/lib/openrouter_client.rb +0 -158
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'sinatra/base'
|
|
5
|
+
require_relative 'apkg_exporter'
|
|
6
|
+
require_relative 'client_factory'
|
|
7
|
+
require_relative 'errors'
|
|
8
|
+
require_relative 'importers/markdown'
|
|
9
|
+
require_relative 'importers/yaml'
|
|
10
|
+
|
|
11
|
+
module AnkiGenerator
|
|
12
|
+
# Localhost preview-and-export UI for the gem, as a modular Sinatra app.
|
|
13
|
+
# Thin controllers only: parsing delegates to Importers, export to
|
|
14
|
+
# ApkgExporter, generation to ClientFactory. The page lives in
|
|
15
|
+
# server/public/index.html (plain static HTML + vanilla JS).
|
|
16
|
+
class Server < Sinatra::Base
|
|
17
|
+
set :root, File.dirname(__FILE__)
|
|
18
|
+
set :default_provider, nil
|
|
19
|
+
set :protection, except: :json_csrf
|
|
20
|
+
|
|
21
|
+
get '/' do
|
|
22
|
+
send_file File.expand_path('server/public/index.html', __dir__)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
post '/parse' do
|
|
26
|
+
payload = json_payload!
|
|
27
|
+
format = payload['format'].to_s
|
|
28
|
+
|
|
29
|
+
cards = case format
|
|
30
|
+
when 'markdown'
|
|
31
|
+
Importers::Markdown.parse(payload['content'].to_s)
|
|
32
|
+
when 'yaml'
|
|
33
|
+
Importers::Yaml.parse(payload['content'].to_s)
|
|
34
|
+
else
|
|
35
|
+
raise ValidationError, "Unknown format '#{format}' (markdown or yaml)"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
json_response(cards:)
|
|
39
|
+
rescue AnkiGenerator::Error => e
|
|
40
|
+
error_json(e.message)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
post '/generate' do
|
|
44
|
+
payload = json_payload!
|
|
45
|
+
client = ClientFactory.build(
|
|
46
|
+
provider: payload['provider'] || settings.default_provider,
|
|
47
|
+
model: empty_to_nil(payload['model']),
|
|
48
|
+
api_key: empty_to_nil(payload['api_key'])
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
cards = client.generate_multiple_flashcards(
|
|
52
|
+
topics: [payload['prompt'].to_s],
|
|
53
|
+
difficulty: payload['difficulty'].to_s.empty? ? 'medium' : payload['difficulty'],
|
|
54
|
+
count: (payload['count'] || 10).to_i
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
json_response(cards:)
|
|
58
|
+
rescue AnkiGenerator::Error => e
|
|
59
|
+
error_json(e.message)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
post '/export' do
|
|
63
|
+
payload = json_payload!
|
|
64
|
+
result = ApkgExporter.export(deck_name: payload['deck_name'].to_s, cards: payload['cards'])
|
|
65
|
+
|
|
66
|
+
content_type result[:content_type]
|
|
67
|
+
headers 'Content-Disposition' => %(attachment; filename="#{result[:filename]}")
|
|
68
|
+
result[:bytes]
|
|
69
|
+
rescue AnkiGenerator::Error => e
|
|
70
|
+
error_json(e.message)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
# Parses the request body as JSON once. Malformed payloads halt with 400.
|
|
76
|
+
def json_payload!
|
|
77
|
+
body = request.body.read
|
|
78
|
+
JSON.parse(body.empty? ? '{}' : body)
|
|
79
|
+
rescue JSON::ParserError => e
|
|
80
|
+
halt 400, { 'Content-Type' => 'application/json' }, { error: e.message }.to_json
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def json_response(payload)
|
|
84
|
+
content_type :json
|
|
85
|
+
payload.to_json
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def error_json(message, status = 422)
|
|
89
|
+
content_type :json
|
|
90
|
+
status status
|
|
91
|
+
{ error: message }.to_json
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def empty_to_nil(value)
|
|
95
|
+
value.nil? || value.to_s.empty? ? nil : value
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnkiGenerator
|
|
4
|
+
# Presentation boundary for user-facing output. Commands and utilities emit
|
|
5
|
+
# through a UI instance instead of writing to $stdout directly, which keeps
|
|
6
|
+
# the library quiet when embedded and makes output assertions trivial in tests.
|
|
7
|
+
class UI
|
|
8
|
+
def initialize(io = $stdout)
|
|
9
|
+
@io = io
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def info(message)
|
|
13
|
+
@io.puts(message)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def success(message)
|
|
17
|
+
@io.puts("✅ #{message}")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def warn(message)
|
|
21
|
+
@io.puts("⚠️ #{message}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def error(message)
|
|
25
|
+
@io.puts("❌ #{message}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/anki_generator.rb
CHANGED
|
@@ -1,116 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
require_relative '
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
yaml_content = YAML.load_file(deck_file)
|
|
22
|
-
|
|
23
|
-
# Handle both old format (array of cards) and new format (with ai_generation config)
|
|
24
|
-
if yaml_content.is_a?(Hash) && yaml_content['ai_generation']
|
|
25
|
-
process_ai_generation(yaml_content)
|
|
26
|
-
else
|
|
27
|
-
self.cards = yaml_content.is_a?(Array) ? yaml_content : []
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def process_ai_generation(config, attachments: nil)
|
|
32
|
-
ai_config = config['ai_generation']
|
|
33
|
-
existing_cards = config['cards'] || []
|
|
34
|
-
|
|
35
|
-
# Generate AI cards if specified and client is available
|
|
36
|
-
if ai_config['topics'] && openrouter_client
|
|
37
|
-
ai_cards = generate_ai_cards(
|
|
38
|
-
topics: ai_config['topics'],
|
|
39
|
-
context: ai_config['context'],
|
|
40
|
-
difficulty: ai_config['difficulty'] || 'medium',
|
|
41
|
-
count: ai_config['count'] || 5,
|
|
42
|
-
attachments: attachments
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
self.cards = existing_cards + ai_cards
|
|
46
|
-
else
|
|
47
|
-
self.cards = existing_cards
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Save the generated cards back to YAML for future reference
|
|
51
|
-
save_generated_cards_to_yaml(config) if ai_config['save_generated'] && openrouter_client
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def generate_ai_cards(topics:, context: nil, difficulty: 'medium', count: 5, attachments: nil)
|
|
55
|
-
if topics.is_a?(Array) && topics.length > 1
|
|
56
|
-
openrouter_client.generate_multiple_flashcards(
|
|
57
|
-
topics: topics,
|
|
58
|
-
context: context,
|
|
59
|
-
difficulty: difficulty,
|
|
60
|
-
count: count,
|
|
61
|
-
attachments: attachments
|
|
62
|
-
)
|
|
63
|
-
else
|
|
64
|
-
topic = topics.is_a?(Array) ? topics.first : topics
|
|
65
|
-
[openrouter_client.generate_flashcard(
|
|
66
|
-
topic: topic,
|
|
67
|
-
context: context,
|
|
68
|
-
difficulty: difficulty,
|
|
69
|
-
attachments: attachments
|
|
70
|
-
)]
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def save_generated_cards_to_yaml(original_config)
|
|
75
|
-
output_file = deck_file.gsub('.yaml', '_generated.yaml')
|
|
76
|
-
|
|
77
|
-
updated_config = original_config.dup
|
|
78
|
-
updated_config['cards'] = cards
|
|
79
|
-
updated_config['ai_generation']['save_generated'] = false # Prevent recursive generation
|
|
80
|
-
|
|
81
|
-
File.open(output_file, 'w') do |file|
|
|
82
|
-
file.write(updated_config.to_yaml)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
puts "Generated cards saved to: #{output_file}"
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def generate_apkg(output_path:)
|
|
89
|
-
deck = Anki2.new({ name: name, output_path: output_path })
|
|
90
|
-
|
|
91
|
-
cards.each do |card|
|
|
92
|
-
deck.add_card(card['front'], card['back'])
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
deck.save
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def add_card(front:, back:)
|
|
99
|
-
cards << { 'front' => front, 'back' => back }
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def sync_with_existing_deck(existing_yaml_file)
|
|
103
|
-
return unless File.exist?(existing_yaml_file)
|
|
104
|
-
|
|
105
|
-
existing_cards = YAML.load_file(existing_yaml_file)
|
|
106
|
-
existing_cards = existing_cards.is_a?(Array) ? existing_cards : existing_cards['cards'] || []
|
|
107
|
-
|
|
108
|
-
# Simple deduplication based on front text
|
|
109
|
-
existing_fronts = existing_cards.map { |card| card['front'] }
|
|
110
|
-
new_cards = cards.reject { |card| existing_fronts.include?(card['front']) }
|
|
111
|
-
|
|
112
|
-
self.cards = existing_cards + new_cards
|
|
113
|
-
|
|
114
|
-
puts "Synced #{new_cards.length} new cards with existing deck"
|
|
115
|
-
end
|
|
116
|
-
end
|
|
3
|
+
require_relative 'anki_generator/version'
|
|
4
|
+
require_relative 'anki_generator/errors'
|
|
5
|
+
require_relative 'anki_generator/ui'
|
|
6
|
+
require_relative 'anki_generator/card'
|
|
7
|
+
require_relative 'anki_generator/apkg_schema'
|
|
8
|
+
require_relative 'anki_generator/apkg_writer'
|
|
9
|
+
require_relative 'anki_generator/file_processor'
|
|
10
|
+
require_relative 'anki_generator/prompt_builder'
|
|
11
|
+
require_relative 'anki_generator/card_schema'
|
|
12
|
+
require_relative 'anki_generator/llm_client'
|
|
13
|
+
require_relative 'anki_generator/client_factory'
|
|
14
|
+
require_relative 'anki_generator/anki_connect_client'
|
|
15
|
+
require_relative 'anki_generator/deck_builder'
|
|
16
|
+
require_relative 'anki_generator/apkg_exporter'
|
|
17
|
+
require_relative 'anki_generator/importers/csv'
|
|
18
|
+
require_relative 'anki_generator/importers/markdown'
|
|
19
|
+
require_relative 'anki_generator/importers/yaml'
|
|
20
|
+
require_relative 'anki_generator/server'
|
data/prompt.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
front: What is the main contribution of the Pattern-defeating Quicksort (pdqsort) paper? back: It introduces a new solution to the Dutch national flag problem, providing a worst-case runtime of O(nk) for inputs with k distinct elements and a hybrid sorting algorithm combining quicksort, insertion sort, and heapsort.
|
|
2
|
+
|
|
3
|
+
Following that pattern, structure
|
|
4
|
+
|
|
5
|
+
Generate as many anki cards deeply focused in bioinformatics about the pdf sent. Make as many as you want. be exhaustive
|
metadata
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: anki_generator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ceb
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: dotenv
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: '2.8'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: '2.8'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: json
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '2.0'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
40
|
+
version: '2.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: ruby_llm
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
@@ -53,80 +53,93 @@ dependencies:
|
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '2.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: rubyzip
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- - "
|
|
59
|
+
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '2.
|
|
61
|
+
version: '2.3'
|
|
62
|
+
- - "<"
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '3.0'
|
|
62
65
|
type: :runtime
|
|
63
66
|
prerelease: false
|
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
68
|
requirements:
|
|
66
|
-
- - "
|
|
69
|
+
- - ">="
|
|
67
70
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '2.
|
|
71
|
+
version: '2.3'
|
|
72
|
+
- - "<"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '3.0'
|
|
69
75
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
76
|
+
name: sinatra
|
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
|
72
78
|
requirements:
|
|
73
79
|
- - "~>"
|
|
74
80
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
81
|
+
version: '4.0'
|
|
76
82
|
type: :runtime
|
|
77
83
|
prerelease: false
|
|
78
84
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
85
|
requirements:
|
|
80
86
|
- - "~>"
|
|
81
87
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
88
|
+
version: '4.0'
|
|
83
89
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
90
|
+
name: sqlite3
|
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
|
86
92
|
requirements:
|
|
87
|
-
- - "
|
|
93
|
+
- - ">="
|
|
88
94
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
90
|
-
|
|
95
|
+
version: '1.6'
|
|
96
|
+
- - "<"
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: '3.0'
|
|
99
|
+
type: :runtime
|
|
91
100
|
prerelease: false
|
|
92
101
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
102
|
requirements:
|
|
94
|
-
- - "
|
|
103
|
+
- - ">="
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: '1.6'
|
|
106
|
+
- - "<"
|
|
95
107
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
108
|
+
version: '3.0'
|
|
97
109
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
110
|
+
name: thor
|
|
99
111
|
requirement: !ruby/object:Gem::Requirement
|
|
100
112
|
requirements:
|
|
101
113
|
- - "~>"
|
|
102
114
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '
|
|
104
|
-
type: :
|
|
115
|
+
version: '1.2'
|
|
116
|
+
type: :runtime
|
|
105
117
|
prerelease: false
|
|
106
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
119
|
requirements:
|
|
108
120
|
- - "~>"
|
|
109
121
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '
|
|
122
|
+
version: '1.2'
|
|
111
123
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
124
|
+
name: webrick
|
|
113
125
|
requirement: !ruby/object:Gem::Requirement
|
|
114
126
|
requirements:
|
|
115
|
-
- - "
|
|
127
|
+
- - ">="
|
|
116
128
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '1.
|
|
118
|
-
type: :
|
|
129
|
+
version: '1.8'
|
|
130
|
+
type: :runtime
|
|
119
131
|
prerelease: false
|
|
120
132
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
133
|
requirements:
|
|
122
|
-
- - "
|
|
134
|
+
- - ">="
|
|
123
135
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '1.
|
|
125
|
-
description: A
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
file and directory attachment processing for context-aware generation,
|
|
129
|
-
support, intelligent content filtering, and flexible deck management
|
|
136
|
+
version: '1.8'
|
|
137
|
+
description: A command-line tool that generates Anki flashcard decks (.apkg) from
|
|
138
|
+
YAML files, direct prompts, or file attachments. Features AI-powered content generation
|
|
139
|
+
via the provider-agnostic ruby_llm gem (Gemini, OpenAI, Anthropic, OpenRouter, Ollama,
|
|
140
|
+
and more), file and directory attachment processing for context-aware generation,
|
|
141
|
+
prompt file support, intelligent content filtering, and flexible deck management
|
|
142
|
+
with sync capabilities.
|
|
130
143
|
email:
|
|
131
144
|
- ceeb.developer@gmail.com
|
|
132
145
|
executables:
|
|
@@ -134,12 +147,55 @@ executables:
|
|
|
134
147
|
extensions: []
|
|
135
148
|
extra_rdoc_files: []
|
|
136
149
|
files:
|
|
150
|
+
- ".gitignore"
|
|
151
|
+
- ".rubocop.yml"
|
|
152
|
+
- ".ruby-version"
|
|
153
|
+
- ".tool-versions"
|
|
154
|
+
- CHANGELOG.md
|
|
155
|
+
- Gemfile
|
|
156
|
+
- Makefile
|
|
137
157
|
- README.md
|
|
158
|
+
- Rakefile
|
|
159
|
+
- anki_generator.gemspec
|
|
138
160
|
- bin/anki_generator
|
|
139
|
-
-
|
|
161
|
+
- docs/CI_SETUP.md
|
|
162
|
+
- docs/architecture/current-v1.3.0.architecture.json
|
|
163
|
+
- docs/architecture/current-v1.3.0.html
|
|
164
|
+
- docs/architecture/current-v1.3.0.visual-check.json
|
|
165
|
+
- docs/architecture/phase3-proposed.architecture.json
|
|
166
|
+
- docs/architecture/phase3-proposed.html
|
|
167
|
+
- docs/architecture/phase3-proposed.visual-check.json
|
|
168
|
+
- docs/phase3-draft.md
|
|
169
|
+
- examples/example_class.rb
|
|
170
|
+
- examples/manual_cards.yaml
|
|
171
|
+
- examples/study_prompt.txt
|
|
172
|
+
- input/input.yaml.example
|
|
140
173
|
- lib/anki_generator.rb
|
|
141
|
-
- lib/
|
|
142
|
-
- lib/
|
|
174
|
+
- lib/anki_generator/anki_connect_client.rb
|
|
175
|
+
- lib/anki_generator/apkg_schema.rb
|
|
176
|
+
- lib/anki_generator/apkg_writer.rb
|
|
177
|
+
- lib/anki_generator/card.rb
|
|
178
|
+
- lib/anki_generator/cli.rb
|
|
179
|
+
- lib/anki_generator/client_factory.rb
|
|
180
|
+
- lib/anki_generator/commands/create_ai_template.rb
|
|
181
|
+
- lib/anki_generator/commands/generate_deck.rb
|
|
182
|
+
- lib/anki_generator/commands/generate_yaml.rb
|
|
183
|
+
- lib/anki_generator/commands/import.rb
|
|
184
|
+
- lib/anki_generator/commands/prompt_based.rb
|
|
185
|
+
- lib/anki_generator/commands/prompt_to_deck.rb
|
|
186
|
+
- lib/anki_generator/commands/push.rb
|
|
187
|
+
- lib/anki_generator/commands/serve.rb
|
|
188
|
+
- lib/anki_generator/commands/test_api.rb
|
|
189
|
+
- lib/anki_generator/deck_builder.rb
|
|
190
|
+
- lib/anki_generator/errors.rb
|
|
191
|
+
- lib/anki_generator/file_processor.rb
|
|
192
|
+
- lib/anki_generator/importers/csv.rb
|
|
193
|
+
- lib/anki_generator/importers/markdown.rb
|
|
194
|
+
- lib/anki_generator/prompt_builder.rb
|
|
195
|
+
- lib/anki_generator/server.rb
|
|
196
|
+
- lib/anki_generator/ui.rb
|
|
197
|
+
- lib/anki_generator/version.rb
|
|
198
|
+
- prompt.txt
|
|
143
199
|
homepage: https://github.com/pinkfloydsito/anki_generator
|
|
144
200
|
licenses:
|
|
145
201
|
- MIT
|
|
@@ -149,6 +205,7 @@ metadata:
|
|
|
149
205
|
changelog_uri: https://github.com/pinkfloydsito/anki_generator/blob/main/CHANGELOG.md
|
|
150
206
|
bug_tracker_uri: https://github.com/pinkfloydsito/anki_generator/issues
|
|
151
207
|
documentation_uri: https://github.com/pinkfloydsito/anki_generator/blob/main/README.md
|
|
208
|
+
rubygems_mfa_required: 'true'
|
|
152
209
|
post_install_message:
|
|
153
210
|
rdoc_options: []
|
|
154
211
|
require_paths:
|
|
@@ -157,14 +214,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
157
214
|
requirements:
|
|
158
215
|
- - ">="
|
|
159
216
|
- !ruby/object:Gem::Version
|
|
160
|
-
version:
|
|
217
|
+
version: 3.1.0
|
|
161
218
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
219
|
requirements:
|
|
163
220
|
- - ">="
|
|
164
221
|
- !ruby/object:Gem::Version
|
|
165
222
|
version: '0'
|
|
166
223
|
requirements: []
|
|
167
|
-
rubygems_version: 3.
|
|
224
|
+
rubygems_version: 3.5.22
|
|
168
225
|
signing_key:
|
|
169
226
|
specification_version: 4
|
|
170
227
|
summary: AI-powered Anki flashcard generator with file attachment support
|