mistri 0.0.3 → 0.1.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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +162 -0
  3. data/README.md +314 -3
  4. data/lib/generators/mistri/install/install_generator.rb +54 -0
  5. data/lib/generators/mistri/install/templates/migration.rb.tt +14 -0
  6. data/lib/generators/mistri/install/templates/model.rb.tt +4 -0
  7. data/lib/mistri/abort_signal.rb +63 -0
  8. data/lib/mistri/agent.rb +340 -0
  9. data/lib/mistri/budget.rb +29 -0
  10. data/lib/mistri/compaction.rb +78 -0
  11. data/lib/mistri/compactor.rb +182 -0
  12. data/lib/mistri/content.rb +89 -0
  13. data/lib/mistri/edit.rb +238 -0
  14. data/lib/mistri/errors.rb +94 -0
  15. data/lib/mistri/event.rb +50 -0
  16. data/lib/mistri/memory.rb +26 -0
  17. data/lib/mistri/message.rb +90 -0
  18. data/lib/mistri/models.rb +43 -0
  19. data/lib/mistri/partial_json.rb +210 -0
  20. data/lib/mistri/providers/anthropic/assembler.rb +205 -0
  21. data/lib/mistri/providers/anthropic/serializer.rb +106 -0
  22. data/lib/mistri/providers/anthropic.rb +106 -0
  23. data/lib/mistri/providers/fake.rb +109 -0
  24. data/lib/mistri/providers/gemini/assembler.rb +163 -0
  25. data/lib/mistri/providers/gemini/serializer.rb +109 -0
  26. data/lib/mistri/providers/gemini.rb +73 -0
  27. data/lib/mistri/providers/openai/assembler.rb +205 -0
  28. data/lib/mistri/providers/openai/serializer.rb +104 -0
  29. data/lib/mistri/providers/openai.rb +72 -0
  30. data/lib/mistri/result.rb +30 -0
  31. data/lib/mistri/retry_policy.rb +47 -0
  32. data/lib/mistri/schema.rb +162 -0
  33. data/lib/mistri/session.rb +124 -0
  34. data/lib/mistri/sinks/action_cable.rb +30 -0
  35. data/lib/mistri/sinks/coalesced.rb +61 -0
  36. data/lib/mistri/sinks/sse.rb +26 -0
  37. data/lib/mistri/skill.rb +15 -0
  38. data/lib/mistri/skills.rb +81 -0
  39. data/lib/mistri/sse.rb +50 -0
  40. data/lib/mistri/stop_reason.rb +25 -0
  41. data/lib/mistri/stores/active_record.rb +47 -0
  42. data/lib/mistri/stores/jsonl.rb +37 -0
  43. data/lib/mistri/stores/memory.rb +22 -0
  44. data/lib/mistri/sub_agent.rb +211 -0
  45. data/lib/mistri/tool.rb +94 -0
  46. data/lib/mistri/tool_call.rb +18 -0
  47. data/lib/mistri/tool_context.rb +15 -0
  48. data/lib/mistri/tool_executor.rb +66 -0
  49. data/lib/mistri/tool_result.rb +23 -0
  50. data/lib/mistri/tools/edit_file.rb +37 -0
  51. data/lib/mistri/tools/find_in_file.rb +36 -0
  52. data/lib/mistri/tools/list_files.rb +16 -0
  53. data/lib/mistri/tools/read_file.rb +38 -0
  54. data/lib/mistri/tools/read_memory.rb +16 -0
  55. data/lib/mistri/tools/update_memory.rb +22 -0
  56. data/lib/mistri/tools/write_file.rb +20 -0
  57. data/lib/mistri/tools.rb +50 -0
  58. data/lib/mistri/transport.rb +187 -0
  59. data/lib/mistri/usage.rb +79 -0
  60. data/lib/mistri/version.rb +1 -1
  61. data/lib/mistri/workspace/active_record.rb +47 -0
  62. data/lib/mistri/workspace/directory.rb +52 -0
  63. data/lib/mistri/workspace/memory.rb +40 -0
  64. data/lib/mistri/workspace/single.rb +48 -0
  65. data/lib/mistri.rb +87 -0
  66. metadata +68 -5
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mistri
4
+ module Workspace
5
+ # One document living wherever the host says: a column on a record, a
6
+ # cache key, anything readable and writable. This is the shape of an
7
+ # agent that edits one page:
8
+ #
9
+ # workspace = Mistri::Workspace::Single.new(
10
+ # path: "page.html",
11
+ # read: -> { page.reload.draft_html },
12
+ # write: ->(html) { page.update!(draft_html: html) }
13
+ # )
14
+ #
15
+ # The document tools then read and edit that column like any document.
16
+ class Single
17
+ def initialize(read:, write:, path: "document")
18
+ @path = path.to_s
19
+ @read = read
20
+ @write = write
21
+ end
22
+
23
+ def read(path)
24
+ path.to_s == @path ? @read.call : nil
25
+ end
26
+
27
+ def write(path, content)
28
+ raise SchemaError, "this workspace holds only #{@path.inspect}" unless path.to_s == @path
29
+
30
+ @write.call(content.to_s)
31
+ nil
32
+ end
33
+
34
+ def delete(path)
35
+ if path.to_s == @path
36
+ raise SchemaError,
37
+ "#{@path.inspect} cannot be deleted, only rewritten"
38
+ end
39
+
40
+ nil
41
+ end
42
+
43
+ def list(prefix = nil)
44
+ prefix.nil? || @path.start_with?(prefix.to_s) ? [@path] : []
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/mistri.rb CHANGED
@@ -1,7 +1,94 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "mistri/version"
4
+ require_relative "mistri/errors"
5
+ require_relative "mistri/stop_reason"
6
+ require_relative "mistri/usage"
7
+ require_relative "mistri/models"
8
+ require_relative "mistri/tool_call"
9
+ require_relative "mistri/content"
10
+ require_relative "mistri/message"
11
+ require_relative "mistri/event"
12
+ require_relative "mistri/abort_signal"
13
+ require_relative "mistri/sse"
14
+ require_relative "mistri/partial_json"
15
+ require_relative "mistri/transport"
16
+ require_relative "mistri/schema"
17
+ require_relative "mistri/edit"
18
+ require_relative "mistri/tool_context"
19
+ require_relative "mistri/tool_result"
20
+ require_relative "mistri/tool"
21
+ require_relative "mistri/workspace/memory"
22
+ require_relative "mistri/workspace/directory"
23
+ require_relative "mistri/workspace/single"
24
+ require_relative "mistri/memory"
25
+ require_relative "mistri/tools"
26
+ require_relative "mistri/skill"
27
+ require_relative "mistri/skills"
28
+ require_relative "mistri/tool_executor"
29
+ require_relative "mistri/budget"
30
+ require_relative "mistri/retry_policy"
31
+ require_relative "mistri/compaction"
32
+ require_relative "mistri/stores/memory"
33
+ require_relative "mistri/stores/jsonl"
34
+ require_relative "mistri/session"
35
+ require_relative "mistri/compactor"
36
+ require_relative "mistri/result"
37
+ require_relative "mistri/agent"
38
+ require_relative "mistri/sub_agent"
39
+ require_relative "mistri/sinks/action_cable"
40
+ require_relative "mistri/sinks/sse"
41
+ require_relative "mistri/sinks/coalesced"
42
+ require_relative "mistri/providers/fake"
43
+ require_relative "mistri/providers/anthropic"
44
+ require_relative "mistri/providers/openai"
45
+ require_relative "mistri/providers/gemini"
4
46
 
5
47
  # Mistri (مستری): the fixer. An agent harness for Ruby applications.
6
48
  module Mistri
49
+ PROVIDERS = { anthropic: Providers::Anthropic, openai: Providers::OpenAI,
50
+ gemini: Providers::Gemini }.freeze
51
+ API_KEY_ENV = { anthropic: "ANTHROPIC_API_KEY", openai: "OPENAI_API_KEY",
52
+ gemini: "GEMINI_API_KEY" }.freeze
53
+
54
+ module_function
55
+
56
+ # Build a provider for a model, inferring which one from the model id and
57
+ # reading its key from the environment unless one is passed.
58
+ #
59
+ # Mistri.provider("claude-opus-4-8")
60
+ # Mistri.provider("gpt-5.5", api_key: key, reasoning: { effort: "high" })
61
+ def provider(model, api_key: nil, **)
62
+ name = provider_name(model)
63
+ klass = PROVIDERS.fetch(name) { raise ConfigurationError, "no provider for #{model.inspect}" }
64
+ key = api_key || ENV.fetch(API_KEY_ENV.fetch(name), nil)
65
+ raise ConfigurationError, "no API key for #{name}" if key.to_s.empty?
66
+
67
+ klass.new(api_key: key, model: model, **)
68
+ end
69
+
70
+ # Build an agent for a model in one call: infers and constructs the provider,
71
+ # then wraps it in the loop.
72
+ #
73
+ # agent = Mistri.agent("claude-opus-4-8", tools: [weather], system: "Be brief.")
74
+ # agent.run("Weather in Lahore?") { |event| ... }
75
+ def agent(model, api_key: nil, provider_options: {}, **agent_options)
76
+ built = provider(model, api_key: api_key, **provider_options)
77
+ Agent.new(provider: built, **agent_options)
78
+ end
79
+
80
+ # Catalogued models infer directly; unknown ids fall back to the id prefix,
81
+ # so a brand-new model works before it is catalogued.
82
+ def provider_name(model)
83
+ Models.find(model)&.provider || infer_provider_name(model)
84
+ end
85
+
86
+ def infer_provider_name(model)
87
+ case model.to_s
88
+ when /\Aclaude/ then :anthropic
89
+ when /\A(gpt|o\d|chatgpt)/ then :openai
90
+ when /\Agemini/ then :gemini
91
+ else raise ConfigurationError, "cannot infer a provider from #{model.inspect}"
92
+ end
93
+ end
7
94
  end
metadata CHANGED
@@ -1,17 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mistri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muhammad Ahmed Cheema
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-04 00:00:00.000000000 Z
11
+ date: 2026-07-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: 'Mistri (مستری) is the fixer: an agent harness for Ruby applications.
14
- First release coming soon.'
13
+ description: 'Mistri (مستری) is the fixer: an agent harness that lives inside your
14
+ app. Durable sessions in your own database, streaming, tools, fire-and-forget human
15
+ approval, steering, compaction, structured output, skills, and sub-agents, across
16
+ Anthropic, OpenAI, and Gemini, with zero runtime dependencies.'
15
17
  email:
16
18
  executables: []
17
19
  extensions: []
@@ -21,14 +23,75 @@ files:
21
23
  - LICENSE
22
24
  - NOTICE
23
25
  - README.md
26
+ - lib/generators/mistri/install/install_generator.rb
27
+ - lib/generators/mistri/install/templates/migration.rb.tt
28
+ - lib/generators/mistri/install/templates/model.rb.tt
24
29
  - lib/mistri.rb
30
+ - lib/mistri/abort_signal.rb
31
+ - lib/mistri/agent.rb
32
+ - lib/mistri/budget.rb
33
+ - lib/mistri/compaction.rb
34
+ - lib/mistri/compactor.rb
35
+ - lib/mistri/content.rb
36
+ - lib/mistri/edit.rb
37
+ - lib/mistri/errors.rb
38
+ - lib/mistri/event.rb
39
+ - lib/mistri/memory.rb
40
+ - lib/mistri/message.rb
41
+ - lib/mistri/models.rb
42
+ - lib/mistri/partial_json.rb
43
+ - lib/mistri/providers/anthropic.rb
44
+ - lib/mistri/providers/anthropic/assembler.rb
45
+ - lib/mistri/providers/anthropic/serializer.rb
46
+ - lib/mistri/providers/fake.rb
47
+ - lib/mistri/providers/gemini.rb
48
+ - lib/mistri/providers/gemini/assembler.rb
49
+ - lib/mistri/providers/gemini/serializer.rb
50
+ - lib/mistri/providers/openai.rb
51
+ - lib/mistri/providers/openai/assembler.rb
52
+ - lib/mistri/providers/openai/serializer.rb
53
+ - lib/mistri/result.rb
54
+ - lib/mistri/retry_policy.rb
55
+ - lib/mistri/schema.rb
56
+ - lib/mistri/session.rb
57
+ - lib/mistri/sinks/action_cable.rb
58
+ - lib/mistri/sinks/coalesced.rb
59
+ - lib/mistri/sinks/sse.rb
60
+ - lib/mistri/skill.rb
61
+ - lib/mistri/skills.rb
62
+ - lib/mistri/sse.rb
63
+ - lib/mistri/stop_reason.rb
64
+ - lib/mistri/stores/active_record.rb
65
+ - lib/mistri/stores/jsonl.rb
66
+ - lib/mistri/stores/memory.rb
67
+ - lib/mistri/sub_agent.rb
68
+ - lib/mistri/tool.rb
69
+ - lib/mistri/tool_call.rb
70
+ - lib/mistri/tool_context.rb
71
+ - lib/mistri/tool_executor.rb
72
+ - lib/mistri/tool_result.rb
73
+ - lib/mistri/tools.rb
74
+ - lib/mistri/tools/edit_file.rb
75
+ - lib/mistri/tools/find_in_file.rb
76
+ - lib/mistri/tools/list_files.rb
77
+ - lib/mistri/tools/read_file.rb
78
+ - lib/mistri/tools/read_memory.rb
79
+ - lib/mistri/tools/update_memory.rb
80
+ - lib/mistri/tools/write_file.rb
81
+ - lib/mistri/transport.rb
82
+ - lib/mistri/usage.rb
25
83
  - lib/mistri/version.rb
84
+ - lib/mistri/workspace/active_record.rb
85
+ - lib/mistri/workspace/directory.rb
86
+ - lib/mistri/workspace/memory.rb
87
+ - lib/mistri/workspace/single.rb
26
88
  homepage: https://github.com/mcheemaa/mistri
27
89
  licenses:
28
90
  - MIT
29
91
  metadata:
30
92
  source_code_uri: https://github.com/mcheemaa/mistri
31
93
  changelog_uri: https://github.com/mcheemaa/mistri/blob/main/CHANGELOG.md
94
+ rubygems_mfa_required: 'true'
32
95
  post_install_message:
33
96
  rdoc_options: []
34
97
  require_paths:
@@ -47,5 +110,5 @@ requirements: []
47
110
  rubygems_version: 3.5.22
48
111
  signing_key:
49
112
  specification_version: 4
50
- summary: 'Mistri: an agent harness for Ruby applications.'
113
+ summary: The agent harness for Ruby applications.
51
114
  test_files: []