phronomy 0.7.1 → 0.9.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/README.md +35 -45
- data/benchmark/baseline.json +1 -1
- data/benchmark/bench_agent_invoke.rb +1 -1
- data/benchmark/bench_context_assembler.rb +11 -3
- data/benchmark/bench_regression.rb +11 -11
- data/benchmark/bench_token_estimator.rb +5 -5
- data/benchmark/bench_tool_schema.rb +2 -2
- data/docs/decisions/011-build-context-as-single-llm-input-authority.md +224 -0
- data/lib/phronomy/agent/base.rb +268 -403
- data/lib/phronomy/agent/checkpoint.rb +118 -0
- data/lib/phronomy/agent/concerns/suspendable.rb +6 -6
- data/lib/phronomy/agent/context/capability/base.rb +689 -0
- data/lib/phronomy/agent/context/capability/scope_policy.rb +54 -0
- data/lib/phronomy/agent/context/instruction/prompt_template.rb +102 -0
- data/lib/phronomy/agent/context/knowledge/base.rb +58 -0
- data/lib/phronomy/agent/context/knowledge/entity_knowledge.rb +102 -0
- data/lib/phronomy/agent/context/knowledge/static_knowledge.rb +58 -0
- data/lib/phronomy/agent/fsm.rb +1 -1
- data/lib/phronomy/agent/invocation_pipeline.rb +108 -0
- data/lib/phronomy/agent/lifecycle/fsm_session.rb +251 -0
- data/lib/phronomy/agent/lifecycle/phase_machine_builder.rb +249 -0
- data/lib/phronomy/agent/react_agent.rb +43 -37
- data/lib/phronomy/agent/runner.rb +2 -2
- data/lib/phronomy/agent/shared_state.rb +2 -2
- data/lib/phronomy/agent/tool_executor.rb +108 -0
- data/lib/phronomy/concurrency/async_queue.rb +157 -0
- data/lib/phronomy/concurrency/blocking_adapter_pool.rb +443 -0
- data/lib/phronomy/concurrency/cancellation_scope.rb +125 -0
- data/lib/phronomy/concurrency/cancellation_token.rb +140 -0
- data/lib/phronomy/concurrency/concurrency_gate.rb +157 -0
- data/lib/phronomy/concurrency/deadline.rb +65 -0
- data/lib/phronomy/{runtime → concurrency}/gate_registry.rb +1 -2
- data/lib/phronomy/{runtime → concurrency}/pool_registry.rb +1 -1
- data/lib/phronomy/configuration.rb +0 -6
- data/lib/phronomy/context.rb +2 -8
- data/lib/phronomy/eval/runner.rb +4 -0
- data/lib/phronomy/eval/scorer/llm_judge.rb +12 -1
- data/lib/phronomy/event_loop.rb +7 -7
- data/lib/phronomy/invocation_context.rb +3 -3
- data/lib/phronomy/knowledge_source.rb +0 -5
- data/lib/phronomy/llm_adapter/ruby_llm.rb +17 -11
- data/lib/phronomy/llm_context_window/assembler.rb +191 -0
- data/lib/phronomy/{context → llm_context_window}/context_version_cache.rb +1 -1
- data/lib/phronomy/{context → llm_context_window}/token_budget.rb +7 -4
- data/lib/phronomy/{context → llm_context_window}/token_estimator.rb +3 -3
- data/lib/phronomy/{agent → multi_agent}/handoff.rb +6 -6
- data/lib/phronomy/{agent → multi_agent}/orchestrator.rb +7 -7
- data/lib/phronomy/{agent → multi_agent}/parallel_tool_chat.rb +4 -4
- data/lib/phronomy/{agent → multi_agent}/team_coordinator.rb +4 -4
- data/lib/phronomy/runtime/runtime_metrics.rb +0 -1
- data/lib/phronomy/runtime.rb +20 -6
- data/lib/phronomy/task_group.rb +1 -1
- data/lib/phronomy/tool.rb +3 -4
- data/lib/phronomy/{tool/agent_tool.rb → tools/agent.rb} +6 -6
- data/lib/phronomy/{tool/mcp_tool.rb → tools/mcp.rb} +9 -9
- data/lib/phronomy/tools/vector_search.rb +70 -0
- data/lib/phronomy/tracing/null_tracer.rb +3 -1
- data/lib/phronomy/vector_store/async_backend.rb +4 -4
- data/lib/phronomy/vector_store/base.rb +2 -2
- data/lib/phronomy/vector_store/embeddings/base.rb +41 -0
- data/lib/phronomy/vector_store/embeddings/ruby_llm_embeddings.rb +47 -0
- data/lib/phronomy/vector_store/in_memory.rb +12 -2
- data/lib/phronomy/vector_store/loader/base.rb +27 -0
- data/lib/phronomy/vector_store/loader/csv_loader.rb +58 -0
- data/lib/phronomy/vector_store/loader/markdown_loader.rb +78 -0
- data/lib/phronomy/vector_store/loader/plain_text_loader.rb +24 -0
- data/lib/phronomy/vector_store/pgvector.rb +2 -2
- data/lib/phronomy/vector_store/redis_search.rb +2 -2
- data/lib/phronomy/vector_store/splitter/base.rb +49 -0
- data/lib/phronomy/vector_store/splitter/fixed_size_splitter.rb +53 -0
- data/lib/phronomy/vector_store/splitter/recursive_splitter.rb +107 -0
- data/lib/phronomy/vector_store.rb +14 -2
- data/lib/phronomy/version.rb +1 -1
- data/lib/phronomy/workflow_context.rb +8 -0
- data/lib/phronomy/workflow_runner.rb +11 -131
- data/lib/phronomy.rb +2 -0
- data/scripts/api_snapshot.rb +11 -9
- metadata +44 -46
- data/lib/phronomy/async_queue.rb +0 -155
- data/lib/phronomy/blocking_adapter_pool.rb +0 -435
- data/lib/phronomy/cancellation_scope.rb +0 -123
- data/lib/phronomy/cancellation_token.rb +0 -133
- data/lib/phronomy/concurrency_gate.rb +0 -155
- data/lib/phronomy/context/assembler.rb +0 -143
- data/lib/phronomy/context/compaction_context.rb +0 -111
- data/lib/phronomy/context/trigger_context.rb +0 -39
- data/lib/phronomy/context/trim_context.rb +0 -75
- data/lib/phronomy/deadline.rb +0 -63
- data/lib/phronomy/embeddings/base.rb +0 -39
- data/lib/phronomy/embeddings/ruby_llm_embeddings.rb +0 -45
- data/lib/phronomy/embeddings.rb +0 -11
- data/lib/phronomy/fsm_session.rb +0 -247
- data/lib/phronomy/knowledge_source/base.rb +0 -54
- data/lib/phronomy/knowledge_source/entity_knowledge.rb +0 -96
- data/lib/phronomy/knowledge_source/rag_knowledge.rb +0 -57
- data/lib/phronomy/knowledge_source/static_knowledge.rb +0 -52
- data/lib/phronomy/loader/base.rb +0 -25
- data/lib/phronomy/loader/csv_loader.rb +0 -56
- data/lib/phronomy/loader/markdown_loader.rb +0 -76
- data/lib/phronomy/loader/plain_text_loader.rb +0 -22
- data/lib/phronomy/loader.rb +0 -13
- data/lib/phronomy/prompt_template.rb +0 -96
- data/lib/phronomy/splitter/base.rb +0 -47
- data/lib/phronomy/splitter/fixed_size_splitter.rb +0 -51
- data/lib/phronomy/splitter/recursive_splitter.rb +0 -105
- data/lib/phronomy/splitter.rb +0 -12
- data/lib/phronomy/tool/base.rb +0 -644
- data/lib/phronomy/tool/scope_policy.rb +0 -50
- data/lib/phronomy/tool_executor.rb +0 -106
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Phronomy
|
|
4
|
-
# Centralises tool execution routing based on {Tool::Base.execution_mode}.
|
|
5
|
-
#
|
|
6
|
-
# This is the single place in the framework that decides *how* a tool call is
|
|
7
|
-
# dispatched:
|
|
8
|
-
#
|
|
9
|
-
# - +:cooperative+ — dispatched via +Runtime#spawn+ through the configured
|
|
10
|
-
# scheduler. Under the +:fiber+ backend this avoids an
|
|
11
|
-
# extra OS thread; under the +:thread+ backend it is
|
|
12
|
-
# backed by +ThreadScheduler+ (one thread per task).
|
|
13
|
-
# - +:blocking_io+ — submitted to +BlockingAdapterPool+ when the runtime
|
|
14
|
-
# provides a pool; falls back to +Runtime#spawn+ otherwise.
|
|
15
|
-
# - +:cpu_bound+ — emits a deprecation-style warning then falls back to
|
|
16
|
-
# +:blocking_io+ routing (no process pool available yet).
|
|
17
|
-
# - +:external_process+ — falls back to +:blocking_io+ routing (no process
|
|
18
|
-
# manager available yet).
|
|
19
|
-
#
|
|
20
|
-
# All paths return an object that responds to +#await+ (+Phronomy::Task+ or
|
|
21
|
-
# +BlockingAdapterPool::PendingOperation+), so callers can collect results
|
|
22
|
-
# uniformly.
|
|
23
|
-
#
|
|
24
|
-
# @note Non-goals
|
|
25
|
-
# ToolExecutor deliberately does NOT provide:
|
|
26
|
-
# - A CPU-bound process pool. CPU-intensive tool work must be handled at the
|
|
27
|
-
# application layer (e.g., fork, Sidekiq, separate OS processes). The
|
|
28
|
-
# framework will not add a +ProcessPoolExecutor+ equivalent.
|
|
29
|
-
# - An external process manager. Spawning or supervising subprocesses is
|
|
30
|
-
# out of scope for this module.
|
|
31
|
-
# - Additional core execution routes beyond scheduler-backed cooperative
|
|
32
|
-
# execution and BlockingAdapterPool-backed blocking I/O isolation.
|
|
33
|
-
# The +:cpu_bound+ and +:external_process+ modes are accepted for
|
|
34
|
-
# compatibility but both fall back to +:blocking_io+ routing with a
|
|
35
|
-
# one-time warning. If a genuinely new core execution route is needed,
|
|
36
|
-
# a new ADR is required.
|
|
37
|
-
# These non-goals follow from the cooperative-first, non-preemptive
|
|
38
|
-
# concurrency model (ADR-010): framework components must not assume the
|
|
39
|
-
# caller's concurrency model, and CPU/process management belongs to the
|
|
40
|
-
# application layer.
|
|
41
|
-
#
|
|
42
|
-
# @api private
|
|
43
|
-
module ToolExecutor
|
|
44
|
-
# Tracks tool classes that have already emitted an execution_mode warning so
|
|
45
|
-
# that the same warning is only logged once per process lifetime.
|
|
46
|
-
WARNED_MODES = Set.new
|
|
47
|
-
WARNED_MODES_MUTEX = Mutex.new
|
|
48
|
-
private_constant :WARNED_MODES, :WARNED_MODES_MUTEX
|
|
49
|
-
|
|
50
|
-
# Dispatches a single tool call asynchronously according to its
|
|
51
|
-
# +execution_mode+ and returns an awaitable.
|
|
52
|
-
#
|
|
53
|
-
# @param tool [Phronomy::Tool::Base] the tool instance to invoke
|
|
54
|
-
# @param args [Hash] argument hash to pass to {Tool::Base#call}
|
|
55
|
-
# @param cancellation_token [Phronomy::CancellationToken, nil]
|
|
56
|
-
# @param runtime [Phronomy::Runtime] runtime to use for spawning
|
|
57
|
-
# (defaults to {Runtime.instance}; injectable for tests)
|
|
58
|
-
# @return [#await] a {Phronomy::Task} or {BlockingAdapterPool::PendingOperation}
|
|
59
|
-
# @api private
|
|
60
|
-
def self.call_async(tool:, args:, cancellation_token: nil, runtime: Phronomy::Runtime.instance)
|
|
61
|
-
ct = cancellation_token
|
|
62
|
-
mode = tool.class.execution_mode
|
|
63
|
-
|
|
64
|
-
# Warn and normalise unsupported modes to :blocking_io.
|
|
65
|
-
# Each (tool class, mode) pair emits the warning at most once per process
|
|
66
|
-
# lifetime to avoid log flooding in high-throughput scenarios.
|
|
67
|
-
if mode == :cpu_bound || mode == :external_process
|
|
68
|
-
warn_key = [tool.class.name, mode]
|
|
69
|
-
newly_warned = WARNED_MODES_MUTEX.synchronize { WARNED_MODES.add?(warn_key) }
|
|
70
|
-
if newly_warned
|
|
71
|
-
msg = if mode == :cpu_bound
|
|
72
|
-
"[Phronomy] Tool #{tool.class.name} declares execution_mode :cpu_bound, " \
|
|
73
|
-
"which has no dedicated executor. " \
|
|
74
|
-
"Falling back to blocking_io (BlockingAdapterPool). " \
|
|
75
|
-
"Use :blocking_io explicitly to suppress this warning."
|
|
76
|
-
else
|
|
77
|
-
"[Phronomy] Tool #{tool.class.name} declares execution_mode :external_process, " \
|
|
78
|
-
"which has no dedicated process manager. " \
|
|
79
|
-
"Falling back to blocking_io (BlockingAdapterPool)."
|
|
80
|
-
end
|
|
81
|
-
if Phronomy.configuration.logger
|
|
82
|
-
Phronomy.configuration.logger.warn(msg)
|
|
83
|
-
else
|
|
84
|
-
warn msg
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
mode = :blocking_io
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
pool = begin
|
|
91
|
-
runtime&.blocking_io
|
|
92
|
-
rescue
|
|
93
|
-
nil
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
if mode == :cooperative || pool.nil?
|
|
97
|
-
runtime.spawn(name: "tool-#{tool.class.name.to_s.split("::").last}") do
|
|
98
|
-
tool.call(args, cancellation_token: ct)
|
|
99
|
-
end
|
|
100
|
-
else
|
|
101
|
-
# Submit directly to pool — no wrapping Task thread required.
|
|
102
|
-
pool.submit(cancellation_token: ct) { tool.call(args, cancellation_token: ct) }
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|