phronomy 0.5.1 → 0.5.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ca63f10e2d505005a6011a8755135e0dea1c3d8e8013ae3b2ea1d3b5ecf13d3
4
- data.tar.gz: 420ec691725b6450a0430cdce90372c13da4e73d7013a630b2aa33a7b72e496d
3
+ metadata.gz: 49b20f3defaed56477f9f1ee375a450d26a770d004c052754cc5c045746587cc
4
+ data.tar.gz: 1d2fe811e467c7d04208b82cc9d9ca5fca9b17d0bf6061aa952a2fb862c23a53
5
5
  SHA512:
6
- metadata.gz: 300b155e482fe0b0015bba5d3985c8d37f2599828d9d87763cc5d9925c3bf399cbee46a658d48a79e152d9b410505609e35a89d3b02db632d51b85280938dc8c
7
- data.tar.gz: 88184d595d04eb1ed1be8c6ec145476a5e1f7e6e02e52658f9d80ad3893a29fbcfc377c736b7c0de10deb14e6105bd9594d6b950bd2fb3afda800e770a2219c4
6
+ metadata.gz: 763cf25297e0c8799ad76bcd362ecb5f1899a9ccd0d90791e119d2d0946c59f7c076f7a00d92e01e64735e90b45d7e1aa5462e41efceee9147daf45ac214551f
7
+ data.tar.gz: 3a30e9198008dd9e4e512c374324b4c1cfda40c2a41762ff160f90ffa8ac98c0669f700d810e899fa661bd68af3a14db0145a00afc4d0e97d560d7de27989db0
data/CHANGELOG.md CHANGED
@@ -7,7 +7,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
- ## [0.5.1] - 2026-05-21
10
+ ## [0.5.3] - 2026-05-20
11
+
12
+ ### Bug Fixes
13
+
14
+ - **Ensure `from_server` closes transport on error** (#95): The short-lived
15
+ transport created inside `McpTool.from_server` is now wrapped in
16
+ `begin/ensure`, so the underlying child process (stdio) is always
17
+ terminated even when `fetch_tool` raises.
18
+ - **Correct `McpTool#close` documentation** (#94): The comment previously
19
+ stated that calling `execute` after `close` raises an error; in practice
20
+ the transport reopens automatically. The comment now reflects actual
21
+ behaviour.
22
+
23
+ ### Documentation
24
+
25
+ - **Fix CHANGELOG date for v0.5.1** (#96): The v0.5.1 entry had an
26
+ incorrect date of 2026-05-21; corrected to 2026-05-20.
27
+
28
+ ---
29
+
30
+ ## [0.5.2] - 2026-05-20
31
+
32
+ ### Bug Fixes
33
+
34
+ - **CHANGELOG correction for v0.5.1 MCP fix** (#90): The v0.5.1 entry
35
+ incorrectly stated that a `Mutex` was added to `StdioTransport#rpc_call`.
36
+ The actual fix was per-instance transport ownership (each `McpTool` instance
37
+ creates its own transport in `initialize`). Corrected the description.
38
+
39
+ ### Enhancements
40
+
41
+ - **Add `McpTool#close`** (#92): Tool instances now expose a `close` method
42
+ that shuts down the underlying stdio child process (`StdioTransport`) or
43
+ releases the HTTP connection (`HttpTransport`). This gives callers a
44
+ deterministic way to clean up resources instead of relying on GC.
45
+
46
+ ### Maintenance
47
+
48
+ - **Archive stale Rails integration design doc** (#91): Added an archived
49
+ notice to `spec/design/17_rails_integration.md` clarifying that Rails
50
+ integration was removed in v0.3.0–v0.5.1 and the document is for
51
+ historical reference only.
52
+
53
+ - **Remove zombie `register_workflow_context` API** (#93): The
54
+ `Phronomy.register_workflow_context`, `workflow_context_registry`, and
55
+ `reset_workflow_context_registry!` methods (along with the backing
56
+ `@workflow_context_registry` and `@registry_mutex` module-level variables)
57
+ were removed from `lib/phronomy.rb`. These existed to support the
58
+ `StateStore` deserialization guard, which was removed in a prior release.
59
+ The API had no remaining callers in the codebase and was not listed in
60
+ the README stability table.
61
+
62
+ ---
63
+
64
+ ## [0.5.1] - 2026-05-20
11
65
 
12
66
  ### Bug Fixes
13
67
 
@@ -17,10 +71,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
71
  `lib/generators/`, `lib/phronomy/railtie.rb`, and all references in
18
72
  `lib/phronomy.rb`.
19
73
 
20
- - **Fix thread-safety of `StdioTransport#rpc_call`** (#86): Concurrent calls
21
- to the same `McpTool` instance could interleave JSON-RPC writes and reads,
22
- corrupting request/response pairing. A `Mutex` is now held around each
23
- write+read cycle. Also adds the missing `require "securerandom"`.
74
+ - **Fix MCP transport ownership** (#86): `McpTool` no longer stores a shared
75
+ transport at class level. `from_server` now uses a short-lived transport only
76
+ to fetch tool metadata and calls `close` immediately after. Each tool instance
77
+ creates its own `StdioTransport` or `HttpTransport` in `initialize`, so
78
+ concurrent callers (e.g. via `Orchestrator#dispatch_parallel`) never share
79
+ stdio streams. No `Mutex` is needed. Also adds missing
80
+ `require "securerandom"` and a no-op `HttpTransport#close` for interface
81
+ consistency.
24
82
 
25
83
  ### Documentation
26
84
 
data/README.md CHANGED
@@ -391,6 +391,13 @@ search_tool = Phronomy::Tool::McpTool.from_server(
391
391
  )
392
392
  ```
393
393
 
394
+ Call `close` when the tool is no longer needed to shut down the underlying
395
+ child process (stdio transport) or release the HTTP connection:
396
+
397
+ ```ruby
398
+ search_tool.close
399
+ ```
400
+
394
401
  ### Conversation History — passing prior messages
395
402
 
396
403
  Phronomy does not manage conversation history internally. The application owns the
@@ -41,8 +41,11 @@ module Phronomy
41
41
  # then close it. Each McpTool instance creates its own transport
42
42
  # so that concurrent callers never share IO streams.
43
43
  transport = build_transport(server_uri)
44
- tool_def = transport.fetch_tool(tool_name)
45
- transport.close
44
+ begin
45
+ tool_def = transport.fetch_tool(tool_name)
46
+ ensure
47
+ transport.close
48
+ end
46
49
  build_tool_class(tool_name, server_uri, tool_def).new
47
50
  end
48
51
 
@@ -82,6 +85,15 @@ module Phronomy
82
85
  @mcp_transport.call_tool(tool_name, args)
83
86
  end
84
87
 
88
+ # Allow callers to deterministically shut down the underlying child
89
+ # process (stdio) or release the HTTP connection. For HttpTransport
90
+ # this is a no-op. After close, calling execute will reopen the
91
+ # transport automatically (stdio restarts the child process; HTTP
92
+ # opens a fresh connection per call).
93
+ klass.define_method(:close) do
94
+ @mcp_transport.close
95
+ end
96
+
85
97
  klass
86
98
  end
87
99
  end
@@ -28,7 +28,13 @@ module Phronomy
28
28
  # @param k [Integer]
29
29
  # @return [Array<Hash>] sorted by descending score
30
30
  def search(query_embedding:, k: 5)
31
- results = @documents.map do |id, doc|
31
+ # Take an atomic snapshot before iterating. Hash#dup is a C-level
32
+ # call that completes without releasing the GVL, so it is atomic with
33
+ # respect to any other Ruby thread. Iterating the copy instead of
34
+ # @documents directly prevents "can't add a new key into hash during
35
+ # iteration" when a concurrent thread calls #add.
36
+ snapshot = @documents.dup
37
+ results = snapshot.map do |id, doc|
32
38
  score = cosine_similarity(query_embedding, doc[:embedding])
33
39
  {id: id, score: score, metadata: doc[:metadata]}
34
40
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phronomy
4
- VERSION = "0.5.1"
4
+ VERSION = "0.5.3"
5
5
  end
data/lib/phronomy.rb CHANGED
@@ -50,42 +50,7 @@ module Phronomy
50
50
  end
51
51
  end
52
52
 
53
- # Registry for WorkflowContext classes that may be serialized to external stores
54
- # (Redis, DB). Call +register_workflow_context+ at application startup so that
55
- # only known classes can be deserialized.
56
- @workflow_context_registry = nil
57
- @registry_mutex = Mutex.new
58
-
59
53
  class << self
60
- # Register one or more WorkflowContext classes that are allowed to be
61
- # deserialized by StateStore backends. When at least one class is registered,
62
- # only registered classes will be accepted by
63
- # +StateStore::Base#safe_state_class+.
64
- #
65
- # Call this once at application startup (e.g. in a Rails initializer).
66
- #
67
- # @param classes [Array<Class>] classes including Phronomy::WorkflowContext
68
- # @example
69
- # Phronomy.register_workflow_context(ScanContext, OtherContext)
70
- def register_workflow_context(*classes)
71
- @registry_mutex.synchronize do
72
- @workflow_context_registry ||= {}
73
- classes.each do |klass|
74
- raise ArgumentError, "#{klass.inspect} is not a Class" unless klass.is_a?(Class)
75
- @workflow_context_registry[klass.name] = klass
76
- end
77
- end
78
- end
79
-
80
- # Returns the current registry Hash, or nil when no class has been registered.
81
- # @return [Hash{String => Class}, nil]
82
- attr_reader :workflow_context_registry
83
-
84
- # Clears the registry. Primarily used in tests.
85
- def reset_workflow_context_registry!
86
- @registry_mutex.synchronize { @workflow_context_registry = nil }
87
- end
88
-
89
54
  def configuration
90
55
  @configuration ||= Configuration.new
91
56
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phronomy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raizo T.C.S